h a l f b a k e r yExperiencing technical difficulties since 1999
add, search, annotate, link, view, overview, recent, by name, random
news, help, about, links, report a problem
browse anonymously,
or get an account
and write.
register,
|
|
|
Please log in.
Before you can vote, you need to register.
Please log in or create an account.
|
Concurrent stackframes execution and matching
When you want to integrate two clean pieces of code together people often write glue code, subclasses or change the interfaces to combine the behaviours together. There's a better way. Imagine you have a security manager, transaction manager and a locking manager and a btree. How do you combine them together without creating a mess of the interfaces? What if you could have concurrent stackframes for each library under integration for each piece of code for each function call and match stacktraces to behaviour . In other words, I specify the stackframe that matches where I want do do something and the compiler automatically weaves the code into the right place. You would need parallel return values. | |
I often write reference implementation APIs.
For example, I wrote a btree, SQL parser, executor and I
wrote multiversion concurrency control implementation.
Then I want to glue them together and this is where it
becomes messy. The complexity rachets upwards when
you combine these systems
together
Independently they are simple and have clear APIs.
You don't want to change the reference API as they're
perfect how it is but if you have another requirement you do
not have much choice in passing around extra context or
changing the signature or using composition
I want to hide this mess and move it to the compiler.
Print out two stacktraces of two different pieces of
code and then Merge them together in an arbitrary order by
weaving the points that each separate method is running
in. And having access to the surrounding context that a
method is executing in. That's this idea.
I kind of want access to the parameters of a function of the
code I am integrating against, and maybe local variables.
I cannot change the invariants of the function being
matched against though and I don't want to change that
code or its interfaces.
So what can we match against? The stackframe! This
would work for an interpreted language but for a compiled
language it's a job for the compiler.
The stackframe represents the execution at this point in
time of the function being executed. And local variables
and branches.
I should be capable of weaving in calls to each and
between my
reference implementations with some glue code that
specifies the matching parameters of the method signature
of intermediary stacktraces of any of the reference
implementation code.
The ultimate matching syntax needs to be tolerant of
signature changes of the underlying reference
implementations.
All security managers have a function that decides if you
can do something. You want to weave this into the btree ln
code.
Essentially you have two execution environments executing
different code in lockstep and have access to each others
signature and local variables.
The stackframe of a function changes as local variables
are changed.
I think the most similar example of this idea is aspect
oriented programming but I think I take a different
approach
Every if statement is a branch. If I want to target a
particular branch of another piece of code I need some way
of labelling the branch. We don't often label our branches.
She no easy
https://stackoverfl...chitecture-on-linux [4and20, May 16 2022]
Client side decorators
https://en.m.wikipe...20the%20X%20server. Client side decorators were historically part of window managers [chronological, May 16 2022]
Server side decorations on wayland
https://blog.martin...ations-and-wayland/ Read the comments [chronological, May 16 2022]
Parallel processing
https://www.dais.un.../4_SharedMemory.pdf now with extra Italians [4and20, May 16 2022]
[link]
|
|
SO many words I don't know. Cool. (+) |
|
|
I'm just going to sit this one out, hang around and learn from the responses if that's okay. |
|
|
This is a hairy beast. If it can't be done with a *nix stackframe, someone has considered or discounted it. |
|
|
// Essentially you have two execution environments executing different code in lockstep and have access to each others signature and local variables. // |
|
|
I have argued that objects or variables should have changeable states which are tracked by a central processor. In this way you might be able to simply assign a number or property to (new) objects without using loops at all. The only loops would be in the central processor. |
|
|
What do you mean by "combine the behaviours together"? |
|
|
So my lock manager does some thing with locks and
my btree does something with leaf and internal
nodes. |
|
|
When there is a split in the btree I need to do
something in the lock manager and vice versa. |
|
|
It leads to a mess of code of mixed responsibilities. |
|
|
The trend of software engineering is single
responsibility pattern but at some point you need to
be responsible for two things to integrate them. |
|
|
So I specify a third place and coordinate the two
things without changing the underlying code of the
pure things. |
|
|
It's like if you have a window manager and a kernel
and a desktop environment. Where do you put
functionality such as cut and paste. |
|
|
See the debate regarding window decorations in
Linux. It's a mess nobody wants to integrate the
work. |
|
|
I should add this is a job for the compiler. |
|
|
Suppose you have a btree class, a SQL Parser class and a
currency-set class, as in your first example. |
|
|
Suppose you have a use case where they will all have to
work together. |
|
|
My first thought is, what is wrong with having a
MyUseCaseHandler class, which owns an instance of Btree,
an instance of SqlParser and an instance of CurrencySet,
and farms out most of its work to those objects? |
|
|
Then I see your example about wanting to do something in
a lock-manager every time there's a split in a btree, and I'm
assuming here that a split in a Btree is an internal
operation, that would not be triggered explicitly from an
API. |
|
|
All right; surely you still have a fairly simple
MyUseCaseHandler class, and you add an optional callback
in your Btree class and then, when you initialise the Btree
belonging to your MyUseCaseHandler, you pass it a callback
function which calls the API on your lock-manager (or
whatever the other class is). |
|
|
Why does that approach not work? Would the provision of
the callback hook count as a change to the reference API? |
|
|
Yes, I think I see. Some compilers might have methods to keep variables in the stack or register longer. |
|
|
Generally speaking, it seems to me that [pertinax] is describing some much preferable serial approach. Would a compiler even let you specify parallel processing? |
|
|
The [link] describes basic parallel processing, using Linux pthreads, whatever that means. You are thereby inviting hellspawn to eat your brain and memory. |
|
|
Of all of chronological's entries, I understand this one the
least, but it likely makes the most sense. I think we've found
an area where he actually knows what he's talking about, or
can at least baffle me with bullshit. |
|
|
Pertinax, I agree with your approach, I too favour
composition over inheritance. But I try use the tell
Don't ask pattern. |
|
|
As for callbacks, the JavaScript world kind of rejects
them for promises. And there are a number of
pipeline libraries for async programming. |
|
|
You've understood the problem. |
|
|
I am thinking of the scenario when you don't have
authority over the entire codebase but one small part.
You don't have authority to modify the code of some
library you're using, you are at the mercy of the library
author to provide callbacks or hooks to enable you to
extend the library with behaviour you want. |
|
|
It's a SOLID principle that classes should be closed to
modification but open to extension. |
|
|
I think how we extend classes or software is painful
so that's why I created this idea. |
|
|
When I used the word parallel I do not mean
threading or using multiple cores on the CPU but the
stackframes of your glue code being sequentially
executed in lockstep with your glue code to "drive"
out the coordination of different pieces of the
system. |
|
|
Print out two stacktraces of two different pieces of
code and then Merge them together in an arbitrary
order by weaving the
points that each separate method is running in. And
having access to the surrounding context that a
method is executing in. That's this idea. |
|
|
If someone asked me to write an extension to IntelliJ
or Postgresql I think I would be not amused as these
are extremely sophisticated pieces of software.
Extending them would require you be intimately
familiar with each of the codebases. They are mature
pieces of software with mature extension
frameworks. But very complicated. It's not something
you can do without a heavy investment in time. |
|
|
I want to be capable of reading any class of a piece
of software and essentially extending it with
knowledge of that classes innermost workings which
is a violation of SOLID but it would mean extending
other people's work would be easier. It would break
on the next release though as everything is moved
around. |
|
|
Usually you know what data you need to glue
together and when to glue it together. This idea
solves that problem. Essentially you are executing
two separate callstacks stack traces simultaneously
but as if it's one single function. It's as if all the code I
am running is a single function and I'm deciding what
to place "around" "before" other code. |
|
|
Usually you end up needing to pass extra parameters
and you change the interface of the code and that
causes breakage. |
|
|
To clarify the glue code would look like pattern
matching syntax on methods, classes and references
to parts of code in libraries and other classes. Kind of
like a patch. |
|
|
I should add that async/await functionality in many
programming languages including JavaScript and
Rust is implemented as a state machine. So the
weaving of methods is doable. |
|
|
I have one clean flow of execution from top to bottom
in this part of the system and another clean flow of
execution from top to bottom over here. |
|
|
How can I pause execution deliberately halfway
through a method and execute this method in the
context of the original method. |
|
|
Without changing the underlying sourcecode. |
|
|
I should probably use the word concurrent and not
parallel as they wouldn't be executed in parallel but
they would be concurrent. |
|
|
//It would break on the next release// |
|
|
{Peers at [chronological] over the top of spectacles} |
|
|
//How can I pause execution deliberately halfway through a method and execute this method in the context of the original method.// |
|
|
By using a scripting language? |
|
| |