The intention is to utilise this helper class, that was developed for the
scheduler stress testing; but this time, it should access the actual allocated
render buffers to generate the load.
This implies to use buffers of a significant size; it turned out that
the existing implementation was imprecise, insofar it always used full multiples
of the configured buffer size, which defeats the purpose of performing
a precisely calibrated number of calculation steps. As long as the buffer size
would remain comparatively small, this drift does not matter much.
Thus I changed the implementation now to ensure that exactly the calibrated
number of steps is performed, using a modulus to map it to the buffer memory.
Furthermore, I plan to use a random-walk pattern in the worker thread
to select from a collection of pre-established »buffer types«, similar
to what happens in the actual engine
The actual mystery, that could ''not'' be clarified,
is why that test did pass previously. Because it was
always broken, insofar it pretended that the output buffer
does hold a valid test frame, while in fact the buffer is
just newly allocated.
The deeper reason behind this mismatch lies in the concept of
''in-place processing'' — which is a very obvious, nullary optimisation,
and thus we want our engine to be ''in-place capable'' in the long run.
Which explains why I did write the dummy-test operations with in-place
processing in mind. Yet the actual version of the render engine leaves
out a lot of future improvements, amongst others the in-place processing.
This implies that — at least at the moment — it is clearly the responsibility
of the processing function to prepare the output buffer, in cases where such
preparation is necessary (and this applies in the case of `TestFrame`,
which needs to be primed with a valid header mark)
This change touches on another unsolved problem in the `TestDomainOntology`:
we need a mechanism to allow the generic builder front-end to set
specific configuration for some kind of processing. Generally speaking,
such things are possible in C++, yet somewhat tricky — and thus I postponed
that aspect and just included a configuration variant, hard-coded for the moment.
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.
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
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«.
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
This is something I wanted to clean-up since a very long time indeed,
but always postponed it, since it requires a lot of nasty clean-up and disentangling....
Several parts had been stashed away into `src/lib/test`, which are not really related:
* the testrunner and testsuite builder
* generic helper utilities
* specialised test-support facilities, e.g. the EventLog
This changeset introduces a new top-level test folder and a namespace `::test`
Code from this folder is linked into a shared library `libtestsupport.so`,
which resides in the linkage hierarchy between »Vessel« and »Vault«,
yet is no longer part of the Lumiera application and only linked into the test-suite.