Commit graph

3762 commits

Author SHA1 Message Date
a19a79b611 Library: modernise thread invocation
the operation to run within the thread can be passed through as lambda;
and with the help of C++11 perfect forwarding we can get rid of the
temporary ThreadStartContext entirely, which removes a lot of
pass-through argument copying
2018-03-24 02:00:51 +01:00
31539f00c8 Library: a function for performing multithreaded microbenchmarks 2018-03-24 01:58:34 +01:00
3104016cf2 DI: set up framework for investigation of performance impact
We are about to switch to Double Checked Locking with C++11 atomics,
and we want some rough numbers regarding the Impact
2018-03-23 23:42:10 +01:00
364dcd5291 DI: verify and improve static sanity checks
esp. for subclass instance creation from within a lambda
2018-03-22 21:43:19 +01:00
d9af3abb0f DI: implement creating singleton from arbitrary (user provided) closure/functor/lambda
this is quite an ugly feature, but I couldn't come up with
any convincing argument *not* to implement it (and its low hanging fruit)
2018-03-22 06:53:56 +01:00
e74576f6b0 DI: pass-through arbitrary arguments for initialisation of a ServiceInstance
...this part is a no-brainer.
However, it is not clear yet if we can (and want to) do something similar for deferred (lazy) instance creation
2018-03-22 04:19:33 +01:00
5c39498929 DI: clean-up and document the TDD test
...written as byproduct from the reimplementation draft.

NOTE there is a quite similar test from 2013, DependencyFactory_test
For now I prefer to retain both, since the old one should just continue
to work with minor API adjustments (and thus prove this rewrite is a
drop-in replacement).

On the long run those two tests could be merged eventually...
2018-03-19 05:34:27 +01:00
83476b3ef1 DI: Reworked dependency-factory implementation draft complete -- move into library headers
This is a complete makeover of our lib::Depend and lib::DependencyFactory templates.
While retaining the basic idea, the configuration has been completely rewritten
to favour configuration at the point where a service is provided rather,
than at the point where a dependency is used.

Note: we use differently named headers, so the entire Lumiera
code base still uses the old implementation. Next step will be
to switch the tests (which should be drop-in)
2018-03-19 03:46:49 +01:00
533ed45d8b DI: expand the concept of our dependency factory to handle service instances (#1086)
Most dependencies within Lumiera are singletons and this approach remains adequate.
Singletons are not "EVIL" per se. But in some cases, there is an explicit
lifecycle, managed by some subsystem. E.g. some GUI services are only available
while the GTK event loop is running.

This special case can be integrated transparently into our lib::Depend<TY> front-end,
which defaults to creating a singleton otherwise.
2018-03-11 03:20:21 +01:00
9ca9b1b89a ViewSpec: clarify how the inline DSL spec is transformed into a rule set
several nested repackaging ctor calls here.
In the end, it's an UICoord array, which is moved into heap storage within the rules set
2018-03-05 00:56:43 +01:00
69f87e994c ViewSpec: decide how to cast the types for building the DSL
we'll use a typedef to represent the default case
and provide the level within the UI-Tree as template parameter for the generic case

This avoids wrapping each definition into a builder function, which will be
the same function for 99% of the cases, and it looks rather compact and natural
for the default case, while still retaining genericity.

Another alternative would have been to inject the Tree-level at the invocation;
but doing so feels more like magic for me.
2018-02-24 04:25:41 +01:00
41b8d12b66 ViewSpec: reconsider how to build and structure the DSL (#1126)
...in the light of all the foundation components and frameworks created meanwhile
2018-02-23 05:07:39 +01:00
b6360b2e9c LocationSolver: automatically inject persp(UIC_ELIDED) (closes #1128)
decided to add a very specific preprocessing here, to make the DSL notation more natural.
My guess is that most people won't spot the presence of this tiny bit of magic,
and it would be way more surprising to have rules like

UICoord::currentWindow().panel("viewer").create()

fail in most cases, simply because there is a wildcard on the perspective
and the panel viewer does not (yet) exist. In such a case, we now turn the
perspective into a "existential quantified" wildcard, which is treated as if
the actually existing element was written explicitly into the pattern.
2018-02-17 05:11:34 +01:00
0f26f1e0f4 LocationSolver: Documentation and clean-up (#1127) 2018-02-17 03:45:07 +01:00
e1dd88970c Library: enable the STL algorithms to work with "Lumiera Forward Iterators"
especially std::find is relevant here.
I consider this only a preliminary solution and need to think it over
more in detail. But, judging from the description given in

http://en.cppreference.com/w/cpp/iterator

and

http://en.cppreference.com/w/cpp/concept/InputIterator

...the standard concept of "input iterator" seems to be closest to our
own concept, albeit it requires things like post increment, and a
reference_type convertible to value_type -- requirements we do not
necessarily support with our more limited "Lumiera Forward Iterator"
2018-02-16 06:48:52 +01:00
66cd1fcea8 UI-Coordinates: fix insidious bug
util::contains used to pick the overload for strings,
i.e. it first converted the UI-Coordinates to diagnostic output format
and then searched that string for '*' to determine if the pattern is explicit

works as expected, but not what you'd intend....
...and breaks spectacularly once you search for something as innocuous as '.'
2018-02-16 06:41:42 +01:00
983c490644 LocationSolver: test coverage for existentially quantified elements (#1128)
...and again spotted some really insidious bugs
2018-02-16 06:37:43 +01:00
0b21e816e3 LocationSolver: implement support for elided elements (#1128)
when used in a pattern for matching against the UI tree,
an element marked as UIC_ELIDED = "." is treated as existentially quantified.

This means, we assume / verify there *is* an element at that level,
but we do not care about what this element actually is. Within the
implementation, the handling is similar to a wildcard, yet such a
spec is not classified as a wildcard (it *is* an explicit element,
just not explicitly named).

The relevant consequence is that such an element matches at a leaf
position, while match on wildcards on leaf positions is prohibited,
to prevent arbitrary and nonsensical wildcard matches against
open ended patterns. Especially we need such an existential pattern
to express a rule to create elements from scratch, but within a
specific window with arbitrary (but existing) perspective.
2018-02-16 06:35:26 +01:00
98cab32a08 LocationSolver: several rule match test cases 2018-02-14 03:02:44 +01:00
92bf317d29 LocationSolver: long explicit path test cases
...and here a bug was hiding. gotcha
2018-02-13 02:46:43 +01:00
e04f61fe0d LocationSolver: length discriminating test cases 2018-02-11 04:16:58 +01:00
820abe2bef LocationSolver: provide DSL notation to write "create clauses" 2018-02-11 04:00:59 +01:00
a1ee7574ef LocationSolver: reorganise and complete the decision logic (#1127) 2018-02-09 23:49:36 +01:00
f8dd3a7030 LocationSolver: draft the success cases for a location solution 2018-02-09 04:10:53 +01:00
66bbf146a6 LocationSolver: implement this additional resolving flavour
coverPartially() now computes coverage solution and moves
that solution into place, while retaining the extraneous, uncovered part
2018-02-09 03:30:45 +01:00
c88a68a2a0 LocationSolver: need yet another flavour of the coordinate resolving mechanism
...this happens when you design a subsystem bottom-up
You build five items just to find out that in fact you need only a sixth item....
2018-02-08 03:00:38 +01:00
6022a8afb1 LocationSolver: draft outline of the solving loop 2018-02-08 02:50:48 +01:00
bf314482da LocationSolver: draft the simple usage scenario (unit test) (#1127) 2018-02-08 00:37:02 +01:00
1238d416fc LocationSolver: draft the DSL syntax for sequential alternatives (#1126)
turns out to be somewhat tricky.
The easy shot would be to use the comma operator,
but I don't like that idea, since in logic programming, comma means "and then".

So I prefer an || operator, similar to short-circuit evaluation of boolean OR

Unfortunately, OR binds stronger than assignment, so we need to trick our way
into a smooth DSL syntax by wrapping into intermediary marker types, and accept
rvalue references only, as additional safeguard to enforce the intended inline
definition syntax typical for DSL usage.
2018-02-07 04:24:33 +01:00
10d2cafba9 LocationSolver: draft entities involved in location solving (#1127)
basically this will be built on top of the path matching / resolving mechanism coded thus far.
but we'll need some additional flags and some DSL magic
2018-02-07 04:03:39 +01:00
136e78d023 DockAccess: decide on next steps towards integration (#1126) 2018-02-01 23:08:43 +01:00
134048949c DockAccess: further planning of the location resolution process 2018-01-25 22:45:05 +01:00
1334dfb00d DockAccess: consider how to access the "location query" service
...which also involves some concept how actually to resolve location specifications
2018-01-15 03:56:28 +01:00
3c32cd5acb UI-top-level: decide upon the relation of ViewLocator and Navigator
...and how the former can rely on the latter, abstracted as LocationQuery
2018-01-15 03:56:28 +01:00
d0b59a1c52 GUI-source: rename "util" namespace to "draw"
...which avoids the possible ambiguity with the global util namespace
Moreover, this name seems more adequate to what we're doing here anyway
2018-01-15 03:56:28 +01:00
22e823fad5 DockAccess: finish setup of allocation specifications within the DSL 2018-01-15 03:56:23 +01:00
b6961e8f03 DockAccess: better pass functor as const& into partial application
seems to be the most orthogonal way to strip adornments from the SIG type
Moreover, we want to move the functor into the closure, where it will be stored anyay.
From there on, we can pass as const& into the binder (for creating the partially closed functor)
2018-01-13 00:58:08 +01:00
90a5d76fc9 DockAccess: solution how to bind partial application into generic lambda
...as it turned out, the result type was the problem: the lambda we provide
typically does not yield an Allocator, but only its baseclass function<UICoord(UICoord)>

solution: make Allocator a typedef, we don't expect any further functionality
2018-01-13 00:20:01 +01:00
5dea8eea1f DockAccess: draft how the partial application-builder for the DSL might work
...but not yet able to get it to compile.
Problem seems to be the generic lambda, which is itself a template.
Thus we need a way to instantiate that template with the correct arguments
prior to binding it into a std::function

been there, seen that recently (-> TreeExplorer, the Expander had a similar problem)
2018-01-12 05:50:01 +01:00
ef74527f6b DOC: eliminate spurious mentions of tr1:: 2018-01-12 03:03:25 +01:00
7385b3f525 DockAccess: pick up planning where I left it last September (#1104)
...this was quite an extensive digression, which basically gave us
a solid foundation for topological addressing and pattern matching
within the "interface space"
2018-01-11 02:48:51 +01:00
7dd69003b5 Navigator: finish path matching resolver for UI coordinates (closes #1107) 2018-01-10 04:42:49 +01:00
722c49e5ff Navigator: finish coverage of path extension 2018-01-10 04:21:42 +01:00
2d66293c32 Navigator: test for path extension now basically working as intended 2018-01-09 02:12:00 +01:00
ff24f81d3f Navigator: implement extension by (partial) UI-Coordinate spec
rationale: sometimes (likely this is even the standard case) we do not just
want to "extend", rather we want to extent at very specific levels.

This is easy to implement, based on the existing building blocks for path manipulation
2018-01-09 00:50:54 +01:00
55c196e5a2 Navigator: define test cases for path extension after coverage 2018-01-08 23:49:24 +01:00
d5209bfe1d Navigator: get the anchor() cases to work as intended 2018-01-07 07:20:41 +01:00
0daeb02e4a UI-Coordinates/Navigator: identify misconception in the Builder
the original construction works only as long as we stick to the "classical" Builder syntax,
i.e. use chained calls of the builder functions. But as soon as we just invoke
some builder function for sake of the side-effect on the data within the builder,
this data is destroyed and moved out into the value return type, which unfortunately
is being thrown away right afterwards.

Thus: either make a builder really sideeffect-free, i.e. do each mutation
on a new copy (which is kind of inefficient and counterfeits the whole idea)
or just accept the side-effect and return only a reference.
In this case, we can still return a rvalue-Reference, since at the end
we want to move the product of the build process out into the destination.

This works only due to the C++ concept of sequence points, which ensures
the original object stays alive during the whole evaluation of such a chained
builder expression.

NOTE: the TreeMutator (in namespace lib::diff) also uses a similar Builder construction,
but in *that* case we really build a new product in each step and thus *must*
return a value object, otherwise the reference would already be dangling the
moment we leave the builder function.
2018-01-07 05:26:16 +01:00
2665ad5bf3 Navigator: supply another mutation operation to make anchorage explicit
...basically just a re-use of existing functionality.
Needs some test coverage though
2018-01-07 02:24:33 +01:00
7434212ecf UI-Coordinates: allow for noexcept move construction 2018-01-06 03:38:52 +01:00