Commit graph

489 commits

Author SHA1 Message Date
eeabbb4f60 Fix test breakage
- some tests are notoriously flaky
- increase resource limits for the testsuite to allow stronger stress tests
- provide a "quick" variant of BufferProviderLoad_test with lowered requirements

Furthermore, investigate test scaffolding in `DummyBuilderContext`,
which was broken due to the clean-up in `DiagnosticOutputSlot`.

It seems that only some placeholder instances are required here,
so that we might be successful with just instantiating the `UnimplementedConnection`

__TODO__: need to supply slightly more implementation into the latter,
so that we're able at least to ''create'' such a connection stub.
2026-06-01 01:47:15 +02:00
cd7581ba76 BufferProvider: investigate tricky race at thread shutdown
...even while this situation is unlikely, it needs to be considered:
A worker thread might terminate unexpectedly, due to an error;
all thread-local objects will be destroyed automatically — while the
`EngineBufferManager` might be processing further allocations requested
by that very thread, and dispatch them towards an already destroyed `LocalMemPool`

This turns out to be a nasty problem, since the whole setup was created
to allow the workers to operate independently from each other; any handshake
or registration/deregistration mechanism would require a lock of sorts,
thereby defeating the whole purpose of the setup.

The best solution I could find is to rely on a instance marker hash,
that can be checked with an atomic read prior to each dispatch of a
memory allocation. The destructor of the local pool would then be able
to ''disengage'', by invalidating that hash.

To evaluate this solution, I developed this mechanism
as a free-standing library component, called `LiveMark`
2026-05-21 01:47:11 +02:00
7448b81d49 Library: improve initial population of ScopedCollection
This is a collection with unique-ownership,
and the ability to create all content objects in ''RAII style''
from the constructor call, using a ''population functor''.

It is often used to maintain a collection of resource handles,
and especially to start a series of threads (for testing).

With the variadic λ-captures from C++20, it is possible to rewrite
the most frequently used population functors to be easier to use.
Notably we can now bind constructor arguments, that will be passed
to each of the created elements — a prominent example being the
thread function when launching several threads. Furthermore,
I added a constructor variant that consumes a Lumiera Iterator.
Adding this kind of generic variants is possible now with C++20,
since overload resolution takes concepts into account.
2026-05-14 22:46:06 +02:00
3a491855e7 Library: introduce a concept for the »Lumiera Forward Iterator«
Well, finally.

Lumiera Iterators were conceived as a concept from the very beginning,
and this idea dates back even before C++11. Furthermore, over time some
''trait templates'' have been developed, to detect if some template argument
might match the known pattern of functions associated with a Lumiera Iterator.

Meanwhile this concept is used pervasively in the whole code base, and also
the traits templates proved to be reliable. It therefore seems that the time is ripe
to gradually introduce a genuine **concept** `lum_iter`

I'll take a defensive approach here, since any mistake would lead to
a massive breakage of compilation. The new concept is defined simply
by delegating to to the tried-and-tested trait template, which is
also renamed `can_IterForEach` ⟼ `can_LumieraIter`

One immediate benefit is that the compiler is now able to select
overloads based on that concept, which allows to drop the tricky
selection of variants based on the SFINAE technique and `enable_if`.

For validation, one very heavily used case of that pattern was switched
in `lib/format-util.hpp', which notably lies in the code-path used by `util::join`
2026-05-14 16:32:54 +02:00
9bd3e550dc BufferProvider: improve configuration of thread-local dispatch
Since thread_local implies a static setup, we need a way how to
build a new service instance. Usually this would be a default construction,
yet there might be services with special init requirements.

Using an explicit template parameter for this setup configuration
allows to make the primary template parameter just the service itself,
which makes the default usage much clearer.
2026-04-18 16:25:14 +02:00
a06ef95e94 BufferProvider: skeleton for thread-local service dispatch
- Use a ''monostate'' as access point to thread-local service instances
 - rely on a configuration-context to setup the actual service
 - investigate runtime overhead using a multithreaded microbenchmark
2026-04-18 01:10:27 +02:00
a0d83b4fe8 Library: investigate design for an opaque inline functor
This is a design study to find out what would be required
to build an opaque function wrapper, similar to `std::function`,
yet without using any heap memory ever.

Such a building block would allow for some interesting options
for a well structured design of elaborate data structures.

This changeset provides an implementation draft.

__Two important findings to note__:
 * it is impossible to get away with just a single function pointer
 * because at the very least we need to invoke the destructor of the
   embedded delegate. Thus something akin to a "manager" is required.
 * this implies that the component would not be so efficient as I hoped,
   since it requires two pointers and requires to emit code for each
   type of delegate.
 * by making the component **NonCopyable**, I avoided the complexities
   of virtual copy support. In case the latter is desired, it would be
   much simpler to switch to a classical OO approach with a VTable
   and use our `PolymorphicValue` wrapper to handle copy and cloning.
2026-04-08 01:53:53 +02:00
0760525ea5 Library: deep dive into type reconciliation and tuple handling
This commit is the aggregated result of extended research
that is only loosely related to current development topics.

One theme was the construction of nested data structures using tuples,
which faces some difficulties due to tuple manipulations being limited
almost entirely to compile-time processing. However, the barrier between
compile-time and runtime can be overcome with the help of a dispatcher
table -- which leads to the secondary problem to handle the diverse
tuple elements with a common, generic functor. Such a functor can be
constructed, if and only if those element types are ''reconcilable''

The STDLIB provides two metafunctions, `std::common_type` and
`std::common_refernce`, which however pose some challenges for the
task at hand, since they include additional processing. In the end,
a custom version of the ''basic type reconciliation'' was implemented
and tested, and then used as foundation to build a dispatcher table
for runtime-indexed access and iteration over tuples.

As an aside, several deeply hidden bugs in our library code were resolved,
and the tuple-helpers, tuple string rendering and associated utilities
were regrouped and modernised.

As result of this research work, the following components are provided:
- meta/common-result
- meta/fun-trampoline
- meta/tuple-index-adaptor
2026-04-07 06:32:23 +02:00
a835a796b2 Library: investigate further ramifications and clean-up Itertools
The detailed analysis of corner cases indicated a lot of hidden dangers
when stretching the `IterExplorer` design beyond its limits.

By deliberate choice, this design was kept open so that advanced cohesive
implementation structures can be built. It is even possible ''and tolerated''
to rely on ''references'' to some degree -- assuming however that the
referred memory location remains stable.

As it turned out, these basic assumptions can be broken by a combination
of read-ahead processing (as is necessary for grouping and filtering),
together with adaptor objects embedded as value, especially when
the resulting pipeline object is then moved or copied during evaluation.

While my general attitude towards such extremely clever implementation
constructs is "don't shoot yourself into your foot unless you need to" --
it seems prudent to clean-up some crappy code from the first attempts
towards an iterator pipeline -- notably some of the »Itertools«.
2026-04-01 01:49:36 +02:00
40d3167d1a Library: integrate automatic adapters to flatten iterable sources
This expands the processing scheme developed thus far, so that
an arbitrary nested iterable can be handled, as long as it can be
adapted by the generic mechanisms provided by IterExplorer.

Notably there is now a type pattern match to distinguish various cases,
even spanning the ''rather esoteric'' possibility that an underlying
iterator produces STL collections by-value.

By examining these special cases, the limitations of the `IteratorExplorer`
design were highlighted, and a number of tricky bugs could be fixed.
2026-03-28 23:27:23 +01:00
00098dd815 Library: develop a flattening primitive for IterExplorer
This is a feature I wasn’t sure for a long time how best to tackle.
It’s worth noting that an initial attempt at `IterExplorer` was based
on the monad pattern, which turned out to be a mistake, since monads
are more of an anti-pattern, than being genuinely useful.

The actual use-case that made me reconsider such a feature it
to build an seamlessly chained sequence from several iterators.

It would be simple to develop a suitable utility as a stand-alone helper,
yet it seemed worth the effort to integrate this into the `IterExplorer`
ecosystem, due to the flexible automatic adaptation to iterable source
pipelines provided therein.

Going this route incurred some cost however, unveiling several defects
related to handling nested iterable types in the generic processing framework.
2026-03-27 23:32:55 +01:00
0178e11e65 BufferProvider: simplify OutputSlot implementation structure
The old implementation relied on two layered APIs:
one for the client and one for the implementer of
the Allocation state. This is logically sound, yet
clumsy in terms of design, since the internal API
turns out to be void of actual meaning.

It seems possible to eliminate this confusing structure
by a clear separation of ''implementation realms''
 * the ''mechanics'' of connection state management
 * the actual implementation of the connection

The first can be provided as generic template subclass,
while the latter should be confined entirely into the
implementation of the `Connection` interface.

Doing so requires to keep each part of the implementation
strictly focused onto its purpose — something I obviously
was not able to see at the time when writing this old
implementation, notably because I was completely guided
and driven by the test/dummy implementation without
considering how an actual implementation of
low-level data output would work.
2026-03-14 03:36:15 +01:00
cc9dbd8a40 BufferProvider: relocate TestFrame and dummy-hash computations
These are generic vehicles to verify computation structures.
Since they are in no way related to our models, they belong into »Vault« layer

Furthermore this reorganisation of test support components is prerequisite
to also move further generic facilities down into the Vault
2026-03-07 23:02:35 +01:00
3caa5cfb03 Tests: reorganise test folders
This resolves a long-standing issue:
we could not use proper include paths for test-helper code that was defined alongside the tests.

Since some test-helper code must now be relocated into the »Vault«-Layer,
I took the opportunity to finally resolve this annoyance. The solution is two-fold
 * introduce a dedicated test-support library
 * remove the quirks that were necessary to support some plain-C tests
Together, this allows to raise the include-directory by one level,
and then to adjust all folder names so that they match the namespace
2026-03-07 00:56:19 +01:00
ada5cefaaf re-arrange tests according to layer structure
the buildsystem will now pick up and link
all test cases according to the layer, e.g.
backend tests will automatically be linked
against the backend + library solely.
2013-01-07 05:43:01 +01:00
8d88ffcdff SCons: rework test definition to link according to layer
tests used to be defined ad hoc and test definitions
are scattered confusingly over various directories.
Now built some simple rules into the buildsystem
to allow organising the tests into layers and
linking them accordingly.

Note: this switches to building shared objects
for the test classes too, which effectively speeds up
both re-building and re-running of test cases
2013-01-07 02:15:05 +01:00
6a3d4777be supplement special format handling for Symbol datatype 2012-12-27 22:32:55 +01:00
a1d98eb457 restore and fix some broken tests
..more to come, especially several of the
QueryResolver based tests are still broken
2012-12-27 03:31:09 +01:00
873d6c3d5c re-activate some tests 2012-12-26 02:01:26 +01:00
9369709a46 fix breakage uncovered by unit-test 2012-12-24 03:20:52 +01:00
5b2668a17c generic query representation (placeholder)
...planned to be replaced later by a real
AST based implementation, which acutally
parses the query definitions
2012-12-03 00:41:57 +01:00
d306bb3cdf fix includes 2012-12-03 00:18:18 +01:00
a79ba2c507 refactor use of HashVal typedef (#722) 2012-12-02 23:03:37 +01:00
5292b19dd6 clean-up and finalise time::Mutation 2012-12-02 01:54:02 +01:00
5dfe5e099f refactor namespaces for query and defaults manager 2012-12-01 08:44:07 +01:00
dd8a88d095 adjustments and stubbing to get it past the compiler 2012-11-26 01:22:01 +01:00
62bfccd67b cleanup: remove the old factory template
This template was a leftover from the early days
of Lumiera development and doesn't provide any
substantial value as an abstraction.

For the more intricate cases, we're using the
lib::MultiFact template, which allows to install
several "fabrication" functions at runtime
2012-10-14 01:30:08 +02:00
88f433f433 successfully implemented another combinator strategy
DOH!
this thime hopefully I've actually succeedd to
created what is actually required in the Dispatcher
2012-10-10 05:20:20 +02:00
016a739a5c WIP back to the original problem: how to dispatch jobs...
brainstorming how to implement the job planning stage

the idea is to built on top of the IterExplorer,
but have the "stack" of re-evaluation integrated
into a custom type, which exploits the static
node network structure to avoid heap allocations

solution idea: again use a builder function?
2012-10-10 05:20:20 +02:00
e76b85fcfa fix test broken by #410 2012-10-10 05:20:19 +02:00
e6a105fbc1 iterator exploring monad finished, passes unit test 2012-10-10 05:20:19 +02:00
3d0d599158 get the depth-first exploration test to work
...using the IterQueue for intermediary results
2012-10-10 05:20:18 +02:00
2c33000346 complement IterStack by a similar wrapper for queue-like access 2012-10-10 05:20:18 +02:00
8ced6758fb initial draft for recursive evaluating iterator monad
tricky design problem, because nothing is known about
the source and result sequences to be built.
2012-10-10 05:20:18 +02:00
41180eb99c rework to allow for recursive evaluation
this enables expansion of a (functional) data structure
until exhaustion -- which is what we need to
build job functors by traversing and expanding
an arbitrarily nested job definition structure
2012-10-10 05:20:17 +02:00
75df583607 raw version of ChainedIter passes unit test 2012-10-10 05:20:17 +02:00
8db5413199 implemented chained-iterators
...using the IterExplorer building blocks
2012-10-10 05:20:17 +02:00
d14b37a71d utility class factored out and covered by test
...a stack which can be Lumiera-iterated
2012-10-10 05:20:16 +02:00
da4a343e9e refactor IterExplorer to allow for more flexible strategy definition 2012-10-10 05:20:16 +02:00
dc3ebd4a8f first working concept for an "iterator monad"
the intention is to use this to simplify
generating render jobs based on the elaborated
dependency network of the render nodes. The key
challenge is to overcome the necessity to
store partially done evaluations as
continuation
2012-10-10 05:20:16 +02:00
3a7db1603e add test for the base case 2012-10-10 05:20:16 +02:00
eedcd69941 draft the IterExplorer design
the tricky part seems to be how to combine the
source iterators into a new monad instance, while
keeping this "Combinator" Strategy configurable

...just passes the compiler, while still lacking
even the generic implementation of joining
together the source iterators
2012-10-10 05:20:16 +02:00
45f4c96c6f change LinkedElements to us a more space efficient iterator
Actually we don't need any backreference to the
container for iterating a singly linked list
2012-10-10 05:20:15 +02:00
378ebe21f0 Fix naming of Iteration control API functions (closes #410)
comes in handy now, since IterStateWrapper uses a similar API
2012-10-10 05:20:15 +02:00
83a0f4b41f Implementation (I) : IterStateWrapper as foundation (passing test) 2012-10-10 05:20:15 +02:00
ab2a6b2fce WIP brainstorming about a monadic iterator
The idea is to avoid building a data structure
for intermediary results, while still being able
to process a variably sized and arbitrary shaped
set of source data
2012-10-10 05:20:15 +02:00
3ef1fb7697 linked list helper template finished and passes test 2012-10-10 05:20:14 +02:00
c33fcf9797 WIP draft a linked list helper template 2012-10-10 05:20:14 +02:00
0ab773ab7c helper to pull all elements from an iterator, yielding the last one 2012-10-10 05:20:13 +02:00
9aec2a9806 allow for fractional scaling of time durations
implemented as extension to the linear combinations.
I decided to use the same "always floor" rule
as employed for time quantisation. Moreover,
we don't support floating point, only rationals
2012-10-10 05:20:12 +02:00