Commit graph

408 commits

Author SHA1 Message Date
c3ebade5d2 BufferProvider: investigate and fix broken allocation
Since the BufferStore implementation component is now supposed
to handle only the memory allocation, a complete end-to end data flow
must be ensured, so that allocation / deallocation functions get all
the relevant information. Notably, the `LocalTag` is now used as an
implementation-defined conduit for further (opaque) marker data.

Since all data passed over this API are simple values (even `LocalTag`
is effectively a 64bit integer), we can now avoid relying on output
parameters or similar side-effect tricks.
2026-02-13 03:17:11 +01:00
cd415c05aa BufferProvider: implement first strike of diagnostics accessors
...just enough to be able to write the assertions in the first test case
(..and the test case fails still, due to the pending work on sorting out
   the implementation APIs between `BufferStage` und `BufferStore`)
2026-02-12 20:22:11 +01:00
e10aa751bb BufferProvider: design a new diagnostics API
To push ahead with the refactoring,
I will build the test/diagnostics API completely anew,
and attach it solely to an instance of `DiagnosticBufferProvider`.

Unfortunately this ''leads us into chainsaw surgery...''
 * it uncovers a host of conceptual contradictions
 * actually, the `HeapMemProvider` was more an implementation
   of diagnostic tracking, than it was an actual `BufferProvider`
   implementation (hence the old name: `TrackingHeapBlockProivder`)
 * and this lured me into using these tracking functions directly,
   while the `DiagnosticBufferProvider` remained in unfinished state.

So basically I have now **disabled** all verification from the Unit-tests.
I'll have to rebuild them from scratch, thereby reproducing the logic/intention
2026-02-12 05:29:03 +01:00
ace20660aa BufferProvider: analyse the existing API
- write some documentation
 - identify some add-on API that must be retracted
 - consider further how to disentangle ''diagnostics'' and ''implementation''
2026-02-12 05:06:13 +01:00
9c5eb11b0c BufferProvider: switch to the new implementation structure
More or less forcibly squeeze all the existing implementation
into the new basic structure with two separate »pillars«

**Breakages**
 - existing code expected the `BufferStore` to transition to ''locked'' state
 - existing code expected `provideLockedBuffer(typeID)` to tail-call the
   `buildHandle()` function of the enclosing `BufferProvider` base implementation
 - various diagnostic usages bypassed the official APIs and called directly
   into the implementation. This is no longer possible; rather, `DiagnosticBufferProvider`
   needs to provide additional diagnostic API to suit those purposes
2026-02-11 02:13:43 +01:00
c21ddc1844 BufferProvider: looking for ways to disentangle the implementation (see #1410)
The outward interface has stood the test of time quite well.
But the back-side towards the implementation is a tangled mess,
presumably due to being developed from prototyping code: the
actual implementation is completely overgrown by diagnostics
and test instrumentation, since running in unit test setup
was the only actual usage of this code ever since.

My first attempt with decomposing into a decorator-chain failed.
Thus the new line of attack is to introduce two implementation
pillars right from top-level
- `BufferStage` : the state and metadata handling
- `BufferStore` : the storage backend
These are defined as nested interfaces, and the further refactoring
starts with subclassing everything, nested as it is.
2026-02-10 00:41:41 +01:00
bb6401aaf3 BufferProvider: reshape diagnostics into a decorator
The intention is to build the tracking functionality from scratch,
while wrapping the old implementation as delegate. Hopefully this allows
to reduce the complexity of the existing implementation step by step,
until I'm ''able to grasp what this implementation does''.

This old implementation works, but is highly problematic code.
The Git history shows that I had already problems to understand this code
while building the DiagnosticOutputSlot, one year later.

To my defense, in both cases (2011 and 2012), I had no clear idea yet
how the processing within the engine would work, and thus I considered
that Buffer Type registry a mere implementation detail, that can be
lumped into the »code behind«.
2026-02-09 03:29:06 +01:00
1ebefbe36e BufferProvider: identify usages of the default BufferProvider
The prototype implementations of BuferProvider and OutputSlot are confusing;
in-depth analysis shows that this is related to intermingling use
of test instrumentation and features of a prototypical default.

To get anywhere with the existing code, it seems we'd need to split off
the test instrumentation (i.e. `DiagnosticBufferProvider`) altogether,
even if this causes duplication of implementation code. Many years ago,
when first implementing this prototype, I had no clear idea what the usage
in the Render Engine entails, yet I noticed that some basic buffer »tracking«
could be used as implementation primitive to simplify the prototyping work.
This might be one of the reasons, why the "code behind" in the protocol
implementations both in `BufferProvider` and `OutputSlot` became so strongly
tangled, so that I way unable to make both protocols orthogonally composable.
2026-02-09 00:59:35 +01:00
256c446705 BufferProvider: consider to disentangle diagnostics and default implementation
The implementation code for `DiagnosticOutputProvider` and `TrackingHeapBlockProvider`
look very confusing and tangled. It seems, instrumentation for tests
got mixed up with the effort to provide a simplistic prototype implementation.

What we need foremost here is the latter; most tests that import the
DiagnosticOutputProvider do not even use any instrumentation....
2026-02-09 00:59:30 +01:00
d00992ff70 BufferProvider: start with some requirement analysis
It seems evident that the the problems with the existing BufferProvider implementation
are rooted in a lack of understanding of the actual usage situation at that time(2011).
This caused a »hexagonal design«, i.e. something entirely driven by uint testing
for the sake of unit testing.

So to identify the unsuitable decisions, some degree of deductive work is necessary,
based on our much better understanding of the Render Engine.

A crucial challenge is that buffer management must perform well
within a massively concurrent environment, and do so without excessive latency.
2026-01-25 02:19:30 +01:00
3fe6d5f54c BufferProvider: define standard usage as test case
This picks up the work for [ticket:1395 resolve integration of BufferProvider with DataSink (#1395)]:
Almost a year ago, before the long hiatus due to important general clean-up
and maintenance work, and the research regarding Video output —
a discrepancy was discovered between the »Buffer Provider Protocol«
and the »Output Slot Protocol«. This mismatch prevents us from building
a simple preliminary `BufferProvider` to be used for the engine integration
as part of the [ticket:1228 »Playback Vertical Slice«].

After re-establisihing the work context, I have read through the new
Render Node code built last year, and distilled the sequence of
buffer management operations that actually happen during a recursive
`pull()` call. With this kowledge, I am now able to fill in the
''standard case for rendering'' — which I was unable to formulate
during the first attempt of building the Render Engine in 2011.

__Next Steps__: Redesign of the standard implementation base of the
`BufferProvider` to prepare for a massively concurrent usage.
2026-01-24 15:13:16 +01:00
aac9ee2934 Bugfix: uninitialised stack-memory used in test
...this bug was spotted as the test failed reproducibly
when built with `-fstack-protector-strong` — which adds
additional "canary" markers to some kinds of problematic
stack storage; this seemed to have the effect that now
the second test uses exactly the same location as the
preceding test, and thus finds valid data in the newly
created work buffers.

There is no reason for using uninitialised storage in this
test (I can recall that I wanted to build a generic helper
and intended to use that as ''virtual overlay'' over existing
memory — but that usage never took place, and the `struct Buffer`
is not a general-purpose tool now, but only made for this
specific test. Thus memory can be easily zero-initialised.
2025-11-15 02:00:11 +01:00
20f3252892 Upgrade: down with typename!!
Yet another chainsaw massacre.

One of the most obnoxious annoyances with C++ metaprogramming
is the need to insert `typename` and `template` qualifiers into
most definitions, to help the compiler to cope with the syntax,
which is not context-free.

The recent standards adds several clarifications, so that most
of these qualifiers are redundant now, at least at places where
it is unambiguously clear that only a type can be given.

GCC already supports most of these relaxing rules
(Clang unfortunately lags way behind with support of newer language features...)
2025-07-06 01:19:08 +02:00
b6a39fa831 Upgrade: simplify comparisons
Now able to remove most complicated comparison operators and most usages of boost::operators...
In most cases it is sufficient just to define one ''spaceship operator'',
and often even that one can be synthesised.

However — we still use boost::operators for arithmetic types,
notably the `lib::time::TimeValue`, which is addable and mutipliable
2025-07-04 03:37:54 +02:00
bad4827b34 Upgrade: Literal can be constexpr
Only minor rearrangements necessary to make that possible with C++20
And while at this change (which requires a full rebuild of Lumiera)

- simplify the defined comparison operators, as C++20 can infer most variations
- also mark various usages of `const char*` either as Literal or CStr

Remark: regarding copyright, up to now this is entirely my work,
        with two major creation steps in 2008 (conception) and
        in 2017 (introduction of a symbol table)
2025-07-02 22:18:39 +02:00
afa7ca2e4d Upgrade: switch to C++23 (see #1245)
The Lumiera »Reference Platform« is now upgraded to Debian/Buster, which provides GCC-14 and Clang-20.
Thus the compiler support for C++20 language features seems solid enough, and C++23,
while still in ''experimental stage'' can be seen as a complement and addendum.

This changeset
 * upgrades the compile switches for the build system
 * provides all the necessary adjustments to keep the code base compilable

Notable changes:
 * λ-capture by value now requires explicit qualification how to handle `this`
 * comparison operators are now handled transparently by the core language,
   largely obsoleting boost::operators. This change incurs several changes
   to implicit handling rules and causes lots of ambiguities — which typically
   pinpoint some long standing design issues, especially related to MObjects
   and the ''time entities''. Most tweaks done here can be ''considered preliminary''
 * unfortunately the upgraded standard ''fails'' to handle **tuple-like** entities
   in a satisfactory way — rather an ''exposition-only'' concept is introduced,
   which applies solely to some containers from the STL, thereby breaking some
   very crucial code in the render entities, which was built upon the notion of
   ''tuple-like'' entities and the ''tuple protocol''. The solution is to
   abandon the STL in this respect and **provide an alternative implementation**
   of the `apply` function and related elements.
2025-06-19 01:52:55 +02:00
d888891d84 clean-up: trifles 2025-06-07 23:59:57 +02:00
20392eee1c clean-up: successfully replaced the old fixed type sequence (closes: #987)
This resolves an intricate problem related to metaprogramming with
variadic templates and function signatures. Due to exceptional complexity,
a direct solution was blocked for several years, and required a better
organisation of the support code involved; several workarounds were
developed, gradually leading to a transition path, which could now
be completed in an focused clean-up effort over the last week.

Metaprogramming with sequences of types is organised into three layers:
- simple tasks can be solved with the standard facilities of the language,
  using pattern match with variadic template specialisations
- the ''type-sequence'' construct `Types<T...>` takes the centre stage
  for the explicit definition of collections of types; it can be re-bound
  to other variadic templates and supports simple direct manipulation
- for more elaborate and advanced processing tasks, a ''Loki-style type list''
  can be obtained from a type-sequence, allowing to perform recursive
  list processing task with a technique similar to LISP.
2025-06-07 18:04:59 +02:00
acc77654d1 clean-up: can now switch remaining downstream usages
after all the relevant library components do support both kinds of
type sequences transparently, any usages in core code can now be
switched over to the new, variadic type sequences.
2025-06-07 01:07:36 +02:00
7aa1698a95 clean-up: prepare for variadic Type-Sequences (see #987)
Attempting to reduce the remaining pre-C++11 workarounds before upgrade to C++20...

As a first step: rename the old type-sequence implementation into `TyOLD`
to make it clearly distinguishable; a new variadic implementation `TySeq`
was already introduced as partial workaround, and the next steps
will be to switch over essential parts of the type-sequence library.
2025-06-02 03:24:44 +02:00
bc6a219543 clean-up: trash ReplacableItem (closes: #1059)
Now looking into largely obsolete library facilities...
Starting from `ScopedHolder`, I found a surprising problem with ''perfect forwarding....''

...which however turned out to be the result of ''sloppy programming'' on my side.
At that time, in 2017, seemingly I was under pressure to define a Session-Command,
which captures a Time-entity as »State Memento«. Which turned out to be impossible,
since the Time entities were conceived as being immutable -- a questionable design
decision (see #1261), which already generated quite some additional complexities.


In the course of this »exercise«, I could again clarify that the implementation
of perfect forwarding works as expected on modern compilers — confusion may arrise
sometimes due to ''copy elision'' (which the compiler is required to perform
since C++17, even when the elided constructor has observable side effects).
And it can be derailed when (as was the case here) a »grab everything« constructor
accidentally ends up generating a copy- or move-constructor for the container class
itself. This is an instance of the problem documented with #963 ...

.... and the best solution is to abide by the rule-of-five (and a half)
and to put that `ReplacableItem` to where it belongs...
2025-05-30 19:12:01 +02:00
d31d4295a4 clean-up: remove gavl_time_t as external dependency
Indeed — this change set is kind of sad.
Because I still admire the design of the GAVL library,
and would love to use it for processing of raw video.
However, up to now, we never got to the point of actually
doing so. For the future, I am not sure if there remains
room to rely on lib-GAVL, since FFmpeg roughly covers
a similar ground (and a lot beyond that). And providing
a plug-in for FFmpeg is unavoidable, practically speaking.

So I still retain the nominal dependency on lib-GAVL
in the Build system (since it is still packaged in Debian).

But it is pointless to rely on this library just for an
external type-def `gavl_time_t`. We owe much to this
inspiration, but it can be expected that we'll wrap
these raw time-values into a dedicated marker type
soon, and we certainly won't be exposing any C-style
interface for time calculations in future, since
we do not want anyone to side-step the Lumiera
time handling framework in favour of working
„just with plain numbers“


NOTE: lib-GAVL hompage has moved to Github:
      https://github.com/bplaum/gavl
2025-05-17 23:12:47 +02:00
555af315b3 Upgrade: improve Doxygen parameters and treat some warnings
- remove obsolete configuration settings
- walk through all settings according to the documentation
  https://www.doxygen.nl/manual/config.html
- now try to use the new feature to rely on Clang for C++ parsing
- walk through the doxygen-warnings.txt and fix some obvious misspellings
  and structural problems in the documentation comments.

With Debian-Trixie, we are now using Doxygen 1.9.8 —
which produces massively better results in various fine points.

However, there are still problems with automatic cross links,
especially from implementation to the corresponding test classes.
2025-04-27 05:00:14 +02:00
96c654f66c Upgrade: address further warnings
- conversion from pointer to bool now counts as ''narrowing conversion''
 - constructor names must not include template arguments (enforced with C++20)
 - better use std::array for some dummy test code

Several further warnings are due to known obsoleted or questionable constructs
and were left as-is (e.g. for ScopedHolder) or just commented for later referral
2025-04-15 23:40:14 +02:00
bf6532a69d Upgrade: address warnings -- deprecated implicit copy
Future C++ versions will no longer generate default copy operations
once any single one was defined explicitly. So the goal is to kind-of
''enforce the rule of five'' (if you define one, define them all).

However, sometimes one of these special operators must be defined for a different reason,
e.g. because it is defined as protected, yet should not be exposed on the public API.
In such cases, any other copy operation which still is valid in the default form
must be declared explicitly ''as defaulted''

Overall this seems to be quite an improvement --
and it highlights (again) some known instances of questionable design,
which are mostly obsoleted and require clean-up anyway, or (as in the case of the
Placements) indicate »placeholder code« where the actual solution still needs to be worked out
2025-04-15 18:32:52 +02:00
efcb456e25 Invocation: ++ Milestone ++ invoke complex render graph
Based on the building blocks developed thus far,
it was possible to assemble a typical media processing chain
 * two source nodes
 * one of these passes data through a filter
 * a mixer node on top to combine both chains
 * time-based automation for processing parameters
As actual computation, hash-chaining on blocks of
reproducible random data was used, allowing to verify
for every data word that expected computations were
carried out, in the expected order.
2025-02-19 23:27:52 +01:00
93812d5a6d Invocation: build a complex Render Node network for integration test
Using basically the same topology as in the preceding test, which focused on connectivity. However, in this case we retrieve actual processing functions from the »Test-Rand« ontology in order to perform hash-chaining computations on full data blocks. And, in addition, a »Param Agent Node« is used.
2025-02-19 19:37:55 +01:00
6c2761b337 Invocation: complement NodeBase_test with simple example
While initially intended as introductory test, it meanwhile
focuses on intricate technical details on the level of
basic building blocks, notably the `FeedManifold`

Now I have added a simple end-to-end demonstration example
how a Render Node is built from scratch, leaving out all
technical details and all convenience front-ends like
the `NodeBuilder` — just one dummy port invoked directly.
2025-02-19 01:30:54 +01:00
8a4060861f Invocation: complete simple test case regarding TurnoutSystem
NodeBase_test demonstrates the building blocks of a Render Node,
and verifies low-level mechanics of those building blocks, which
can be quite technical. At the top of this test however are some
very basic interactions, which serve as an introduction.

__Remark__: renamed the low-level technical dispatch-access
for the parameter-accessors in `TurnoutSystem` to be more obvious,
and added comment (I was confused myself how to use them properly)
2025-02-18 23:55:58 +01:00
b7fc2df478 Invocation: NodeBuilder now handles all cases of partial-closure
This is a crucial feature, discovered only late, while building
an overall integration test: it is quite common for processing functionality
to require both a technical, and an artistic parametrisation. Obviously,
both are configured from quite different sources, and thus we need a way
to pre-configure ''some parameter values,'' while addressing other ones
later by an automation function. Probably there will be further similar
requirements, regarding the combination of automation and fixed
user-provided settings (but I'll leave that for later to settle).

On a technical level, wiring such independent sources of information
can be quite a challenging organisational problem — which however can be
decomposed using ''partial function closure'' (as building a value tuple
can be packaged into a builder function). Thus in the end I was able to
delegate a highly technical problem to an existing generic library function.
2025-02-18 20:42:25 +01:00
a5a3d46b6a Invocation: generalise partial-closure cases
With these additions, all conceivable cases are basically addressed.

Take this as opportunity to investigate how the existing implementation
transports values into the Binder, where they will be stored as data fields.
Notably the mechanism of the `TupleConstructor` / `ElmMapper` indeed
''essentially requires'' to pass the initialisers ''by-reference'',
because otherwise there would be limitations on possible mappings.

This implies that not much can be done for ''perfect forwarding'' of initialisers,
but at least the `BindToArgument` can be simplified to take the value directly.
2025-02-17 21:18:37 +01:00
769060b9dd Invocation: extract partial closure functionality
What emerges here, seems to be a generic helper to handle
partial closure of ''tuple-like'' data records. In any case,
this is highly technical meta-programming code and mandates
extraction into a separate header — simplifying `NodeBuilder`
2025-02-16 23:16:46 +01:00
3611bc94ee Invocation: investigate ways to provide partial application
...on top of the parameter-decorating functionality developed thus far.
The idea is to allow in the `NodeBuilder` to supply ''some parameters''
directly, while the remaining parameters will be drawn from automation.

Several years ago, I developed some helpers for partial function closure.
Unfortunately these utils are somewhat limited, and rely on some pre-C++11
constructs, yet seem to be usable for the task at hand, since parameters
are always expected as value objects by definition.

This changeset shows a working proof-of concept for left-closing a
parameter tuple with 5 elements; this turns out to surprisingly difficult
due to the full genericity of the acceptable parameter-aggregates...
2025-02-15 23:47:21 +01:00
79b45601c0 Invocation: rearrange for clearer definitions
seemingly the definition can not be much simplified,
since there is no way around handling several definition flavours
of the processing-functor distinctly.

However, the definitions can be rearranged to be clearer,
the resulting type of the `FeedPrototype` can be deduced from the
builder function, and more stringent assertions can be added
2025-02-13 16:27:50 +01:00
0e5ffe7780 Invocation: draft a way to decorate the processing-functor
...the idea is to limit the scope of possible changes
and rather directly accept a functor to transform the parameters.
We need then to account for the possible flexibility in processing-functor
arguments, while in fact only two cases must be actually handled.

''This proof-of-concept works in test setup''
2025-02-11 17:15:32 +01:00
61c685fa9f Invocation: draft missing feature for integration test
It seemed that the integration test will end up as a dull repetition
of already coded stuff, just with more ports and thus more boilerplate;
and so I reconsidered what an actually relevant integration test might encompass
- getting parameters from the invocation
- translating and wiring parameters
- which entails to adapt / partially close a processing function!

Thus — surprise — there is a new feature not yet supported by the `NodeBuilder`,
which would be very likely to be used in many real-world use cases: which is
to adapt the parameter tuple expected by the binding from the library.
Obviously we want this, since many »raw« processing functions will expose a mix
of technical and artistic parameters; and we'd like to ''close'' the technical ones.

Such a feature ''should be implementable,'' based on the already developed
technique with the »cross builder«, which implies to switch the template arguments
from within a builder expression. We already do this very thing for adapting
parameter functor, and thus the main difficulty would be to compose an
adaptor functor to the correct argument of the processing functor...

Which is... (well, it is nasty and technical, yet feasible).
2025-02-11 01:10:25 +01:00
8694d9ebc1 Invocation: also provide a mixer node backed by ''Test Rand'' 2025-02-10 22:48:31 +01:00
72d7a6c5b8 Invocation: ''Test Rand'' filter node test pass 2025-02-10 03:41:05 +01:00
ccb10f3c65 Invocation: chase down insidious use-after-free problem
Just wanted to use a helper function to build a source-data node.
However, the resulting node had a corrupted Node-ID spec.
Investigation with the debugger showed that the ID was still valid
while in construction and shows up corrupted after returning from the
helper function.

As it turned out, the reason is related to the de-duplication of ProcID data.
While the de-duplicated strings themselves are ''not'' affected, the corruption
happened by an intermediate instance of ProcID, which was inadvertently created
and bound by-value to the builder-λ. The created Port then picks up a reference
to this temporary, leading to the use-after-free of the string_view obejcts.

Obviously, `ProcID` must not be instantiated other than through the static
front-end `ProcID::describe`. Due to the private constructor, I can not make this
object non-copyable (because then the hash-set would not be allowed to emplace it).
But making it at least move-only will provoke a compiler error whenever binding
to a lambda capture by value, which hopefully helps to pinpoint this
insidious problem in the future...
2025-02-10 03:15:28 +01:00
5121bce156 Invocation: cover definition of a »Test-Rand« filter-node
The scheme to provide preconfigured nodes with random `TestFrame` data
seems to be suitable and easy to extend to further cases; should however
always document the setup through a dedicated case in `NodeDevel_test`
2025-02-09 23:05:41 +01:00
b9b80ce923 Invocation: draft setup for a Test-Node for data-manipulation
Seems to be straight forward now, based on the implementation
of `TestFrame` manipulation provided by the »Test Rand Ontology«


__Remark__: the next goal is to reproduce the complex Node tree
with operations on TestFrame and then to invoke these and verify results.
2025-02-09 18:04:39 +01:00
f767cce77b Invocation: also invoke all these nodes
...while this is not the main objective of this test case,
and another test will focus on invocation with full-fledged
`TestFrame` buffers and hash computation...

...it is still a nice achievement to see that these simple
algebraic operations used for demonstration can actually be
invoked in the whole connected network :-)
2025-02-09 01:44:45 +01:00
d54dbc93df Invocation: verify connectivity on complex network 2025-02-08 22:42:13 +01:00
dbbdac02c4 Invocation: now able to code verifications for the demo-network
Using a Node network with
 * two source nodes
 * one of them chained up linearly with a filter node
 * then on top a mix node to combine both chains

Can now verify the generated port specs and verify proper connections
at node level and at port level
2025-02-08 19:39:00 +01:00
72d7986b5e Invocation: build a DSL to verify connectivity (see #1377)
This was a lot of intricate technical work,
and is now verified in-depth, covering all possible cases.

__We can now__
 * build Nodes
 * verify in detail correct connectivity
 * read Node-IDs and processing specifications
 * maintain a symbolic spec for the arguments of a Port

(and beyond that, we can also **invoke nodes**, which remains to be formally verified)
2025-02-05 00:25:02 +01:00
d5a47bf3e4 Invocation: consider how to verify connectivity
An essential goal still to reach is a verification of the `NodeBuilder`'s products
Relying on the low-level diagnostic facilities pioneered last days,
it should now be possible to define simple and readable connectivity-clauses,
allowing to build some connected nodes and then verify the connections explicitly.
2025-02-04 20:25:33 +01:00
fa720ae975 Invocation: for now only set flags by builder
Handling of extended attributes in conjunction with the hash
turns out to be a rather complicated topic, with some tricky fine details.
And, most important, at the moment I am lacking the proper perspective
to address it and find adequate solutions. Luckily, the cache-key is
not required at the moment, ''and so this topic will be postponed''

As a minimum to complete the diagnostics functions, it is sufficient to set
the appropriate flags in the `ProcID` directly -- and to add some convenience wrappers.
2025-02-04 00:22:55 +01:00
583b73bc62 Invocation: now able to access predecessor-ports
...exploiting the ''backdoor access'' bypassing the VTable,
as made possible by a common congruent storage layout.

This is a first proof-of-concept, but also shows that the demo nodes
in NodeMeta_test are wired as expected. What is needed now is to make
this diagnostic access easier to invoke and more bullet-proof, by setting
the proper Attribute bits directly in the `NodeBuilder`
2025-02-03 03:54:21 +01:00
bcdcb36615 Invocation: rearrange MediaWeavingPattern storage layout
...to create an ''access path for diagnostics'' and further evaluations
while ''bypassing the VTable.''

It is a well-known downside of specifically typed, highly optimisable
template-based code to create a dangerous leverage for generating spurious,
mostly identical virtual function instances added for secondary concerns.

Thus it is a consequence of this design choice, either to forego some diagnostic
and analytical possibilities, or to exploit ''other means'' for retrieving
internal data, which is needed for tangential purposes only. The solution
pursued hereby exploits similar layout of various ''weaving pattern''
template instances to create an ''access backdoor'' for use cases
beyond the primary performance-critical path.
2025-02-03 03:27:06 +01:00
ead494e465 Invocation: Argument-spec evaluation sufficiently complete for now
Some additional tests to challenge the parser, which seems to work well.
Without extended analysis into the usage of those node specifications,
it is pointless to expand further on its capabilities. For now, it is
sufficient to have a foundation for hash-computation in place.

__Note__: found a nifty way to give lib::Several an easy toString rendering,
without cranking up the header inclusion load.
2025-02-02 17:22:16 +01:00