not quite sure how to get the design straight.
Also a bit concerned because we'll get this much indirections;
the approach to send invocations via the UI-Bus needs to prove its viability
Did a full review of state and locking logic, seems airtight now.
- command processing itself is unimplemented, we log a TODO message for now
- likewise, builder is not implemented
- need to add the deadlock safeguard #1054
We found out that it's best to run it single threaded
within the session loop thread. This does not mean the Builder
itself is necessarily single threaded, but the Builder's top level
will block any other session operation, and this is a good thing.
For this reason it makes more sense to have the Builder integrated
as a component into the session subsystem.
after reading some related code, I am leaning towards a design
to mirror the way command messages are sent over the UI-Bus.
Unfortunately this pretty much abandons the possibility to
invoke these operations from a client written in C or any
other hand made language binding. Which pretty much confirms
my initial reservation towards such an excessively open
and generic interface system.
...this means to turn Looper into a state machine.
Yet it seems more feasible, since the DispatcherLoop has a nice
checkpoint after each iteration through the while loop, and we'd
keep that whole builder-dirty business completely confined within
the Looper (with a little help of the DispatcherLoop)
Let's see if the state transition logic can actually be implemented
based just on such a checkpoint....?
....if by some weird coincidence, a command dispatched into the session
happens to trigger session shutdown or re-loading, this will cause a deadlock,
since decommissioning of session data structures must wait for the
ProcDispatcher to disable command processing -- and this will obviously
never happen when in a callstack below some command execution!
After some consideration, it became clear that this service implementation
is closely tied to the DispatcherLoop -- which will consequently be
responsible to run and expose this service implementation
need to keep state variables on both levels,
since the session manager (lifecycle) "opens" the session
for external access by starting the dispatcher; it may well happen
thus that the session starts up, while the *session subsystem*
is not(yet) started
mark TODOs in code to make that happen.
Actually, it is not hard to do so, it just requires to combine
all the existing building blocks. When this is done, we can define
the "Session" subsystem as prerequisite for "GUI" in main.cpp
Unless I've made some (copy-n-paste) mistake with defining the facades,
this should be sufficient to pull up "the Session" and automatically
let the Gui-Plugin connect against the SessionCommandService
up to now this happened from the GuiRunner, which was a rather bad idea
- it can throw and thus interfer with the startup process
- the GuiNotification can not sensibly be *implemented* just backed
by the GuiRunner. While CoreService offers access to the necessary
implementation facilities to do so
so the true reason is an inner contradiction in the design
- I want it to be completely self similar
- but the connection to CoreService does not conform
- and I do not want to hard code CoreService into the Nexus classdefinition
So we treat CoreService as uplink für Nexus and Nexus as uplink for CoreService,
with the obvious consequences that we're f**ed at init and shutdown.
And since I want to retain the overall design, I resort to implement
a short circuit detector, which suppresses circular deregistration calls
Decision was made to use the CoreService as PImpl to organise
all those technical aspects of running the backbone. Thus,
the Nexus (UI-Bus hub) becomes part of CoreService
...problem is, I actually don't know much about what kinds of markers
we'll get, and how we handle them. Thus introducing a marker kind
is just a wild guess, in order to get *any* tangible attribute
this is a tricky problem and a tough decision.
After quite some pondering I choose to enforce mandatory fields
through the ctor, and not to allow myself cheating my way around it
it occurred to me that effectively we abandoned the use of
a business facade and proxy model in the UI. The connection
becomes entirely message based now.
To put that into context, the originally intended architecture
never came to life. The UI development stalled before this could
happen; possibly it was also hampered by the "impedance mismatch"
between our intentions in the core and such a classical, model centric
architecture. Joel several times complained that he felt blocked; but
I did not really understand this issue. Only recently, when I came to
adapting the timeline display to GTK-3, I realised the model centric
approach can not possibly work with such an open model as intended
in our case. It would lead to endless cascades of introspection.
these are just empty class files, but writing a basic description
for each made me flesh out a lot of organisational aspects of what
I am about to build now
...it seemed first that we'd might run into a very fundamental problem;
but after some consideration it turns out the interspersed display manager
and the decoupling between model/presenter and widget happens to mitigate
this problem as well.
bottom line
- seems we need to do that manually
- must wait until in the on_draw() callback
- use Container::foreach() to visit all child widgets
- Layout::set_size()
- define tasks to be addressed during investigation
- read documentation, identify problematic aspects
- prepare a child widget class to be placed on the canvas
actually this is a pragmatic extension for some special use cases,
and in general rather discurraged, since it contradicts the
established diff semantics. Yet with some precaution, it should
be possible to transport information via an intermediary ETD
Map -> ETD -> Map
...this is the first attempt to integrate the Diff-Framework into (mock) UI code.
Right now there is a conceptual problem with the representation of attributes;
I tend to reject idea of binding to an "attribute map"
the generic typing to DiffMutatble does not make much sense,
since the desired implementation within gui::ctrl::Nexus
is bound to work on Tangibles only, since that is what
the UI-Bus stores in the routing table
at first, this seemed like a good idea, but it caused already
numerous quirks and headache all over the place. And now, with
the intent to switch to the TreeMutator based implementation,
it would be damn hard to retain these features, if at all
possible.
Thus let's ditch those in time and forget about it!
this is a subtle change in the semantics of the diff language,
actually IMHO a change towards the better. It was prompted by the
desire to integrate diff application onto GenNode-trees into the
implementation framework based on TreeMutator, and do away with
the dedicated implementation.
Now it is a matter of the *selector* to decide if a given layer
is responsible for "attributes". If so, then *all* elements within
this layer count as "attribute" and an after(Ref::ATTRIBS) verb
will fast forward behind *the end of this layer*
Note that the meta token Ref::ATTRIBS is a named GenNode,
and thus trivially responds to isNamed() == true
...instead of using a hand written implementation,
the idea is to rely on the now implemented building blocks,
with just some custom closures to make it work.
- esp. verify the proper inclusion of the Selector closure in all Operations
- straighten the implementation of Attribute binding
- clean-up the error checking helpers
In Theory, acceptSrc and skipSrc are to operate symmetrically,
with the sole difference that skipSrc does not move anything
into the new content.
BUT, since skipSrc is also used to implement the `skip` verb,
which serves to discard garbage left back by a preceeding `find`,
we cannot touch the data found in the src position without risk
of SEGFAULT. For this reason, there is a dedicated matchSrc operation,
which shall be used to generate the verification step to properly
implement the `del` verb.
I've spent quite some time to verify the logic of predicate evaluation.
It seems to be OK: whenever the SELECTOR applies, then we'll perform
the local match, and then also we'll perform the skipSrc. Otherwise,
we'll delegate both operations likewise to the next lower layer,
without touching anything here.
This is the first skeleton to combine all the building blocks,
and it passes compilation, while of course most of the binding
implementation still needs to be filled in...
- default recommendation is to implement DiffMutable interface
- ability to pick up similar non-virtual method on target
- for anything else client shall provide free function mutatorBinding(subject)
PERSONAL NOTE: this is the first commit after an extended leave,
where I was in hospital to get an abdominal cancer removed.
Right now it looks like surgery was successful.
this is at the core of the integration problem: how do we expose
the ability of some opaque data structure to create a TreeMutator?
The idea is
- to use a marker/capability interface
- to use template specialisation to fabricate an instance of that interface
based on the given access point to the opaque data structure
but unfortunately this runs straight into a tough problem,
which I tried to avoid and circumvent all the time:
At some point, we're bound to reveal the concrete type
of the Mutator -- at least to such an extent that we're
able to determine the size of an allocator buffer.
Moreover, by the design chosen thus far, the active
TreeMutator instance (subclass) is assumed to live within
the top-level of a Stack, which means that we need to
place-construct it into that location. Thus, either
we know the type, or we need to move it into place.
the plan is to put together an integration test
of diff application to opaque data through the TreeMutator,
using the now roughly finished binding primitives.
moreover, the idea is to apply precisely the same diff sequence,
as was used in the detail test (TreeMutatorBinding_test).
NOTE: right now, the existing placehoder code applies this sequence
onto a Rec<GenNode>. This should work already -- and it does,
BUT the result of the third step is wrong. Really have to
investigate this accidental finding, because this highlights
a conceptual mismatch in the handling of mixed scopes.
...which mostly just is either ignoring the
operations or indicating failure on attempt to
'reorder' attributes (which don't have any notion of 'ordering')
overall, the structure of this implementation is still rather confusing,
yet any alternatives seem even less convincing
- if we want to avoid the delegation to base-class, we'd have
to duplicate several functions and the combined class would
handle two distinct concerns.
- any attempt to handle the IDs more "symmetrically" seems to
create additional problems on one side or the other