Commit graph

23 commits

Author SHA1 Message Date
d91d0b5926 Invocation: provide functionality to connect lead ports explicitly
...which then also allow to fill in the missing parts for the
default 1:1 wiring scheme, which connects each »input slot«
of the processing function with the corresponding ''lead node''
2024-10-25 18:13:55 +02:00
43373e11e7 Invocation: prepare mechanism for default input wiring
The intention is to offer an automatic 1:1 association
between the »input parameter slots« of the processing function
and the ''lead nodes,'' thereby always using the same default
port, corresponding to the current port number under construction.

Unfortunately, the preceding refactoring removed the information
necessary for a simple implementation, as the port array is now
built up late, in the final build() function...
2024-10-25 05:10:16 +02:00
0144049f9d Invocation: reconsider data access and allocator usage from Builder
The next step is to round out the first prototypical implementation,
which requires access to ''lead node ports'' and thereby generally
places focus on the interplay of ''data builders'' within the ongoing
build process. While the prototype still uses the fall-back to simple
heap allocation, notably the intended usage will require to wire-through
the connection to a single `AllocationCluster`. This poses some
challenge, since further ''data builders'' will be added step-wise,
implying that this wiring can not be completed at construction time.

Thus it seems indicated to slightly open-up the internal allocator
policy base template used by `lib::SeveralBuilder` to allow for some
kind of ''cross building'' based on a shared compatible base allocator
type, so that the allocation policy wiring can be passed-on from an
existing `SeveralBuilder`
2024-10-23 16:27:09 +02:00
554a64e212 Invocation: solve passing of the function definition
- the chaining constructor is picked reliably when the
  slicing is done by a direct static_cast

- the function definition can be passed reliably in all cases
  after it has been ''decayed,'' which is done here simply by
  taking it by-value. This is adequate, since the function
  definition must be copied / inlined for each invocation.

With these fixes, the simplest test case now for the first time
**runs through without failure**
2024-10-22 05:59:00 +02:00
df37fec500 Invocation: switch WeavingBuilder to produce the result via λ
This change allows to disentangle the usages of `lib::SeveralBuilder`,
so that at any time during the build process only a single instance is
actively populated, all in one row — and thus the required storage can
either be pre-allocated, or dynamically extended and shrinked (when
filling elements into the last `SeveralBuilder` currently activated)

By packaging into a λ-closure, the building of the actual `Port`
implementation objects (≙ `Turnout` instances) is delayed until the
very end of the build process, and then unloaded into yet another
`lib::Several` in one strike. Temporarily, those building functor
objects are „hidden“ in the current stack frame, as a new `NodeBuilder`
instance is dropped off with an adapted type parameter (embedding the
λ-type produced by the last nested `PortBuilder` invocation, while
inheriting from previous ones.

However, defining a special constructor to cause this »chaining«
poses some challenge (regarding overload resolution). Moreover,
since the actual processing function shall be embedded directly
(as opposed to wrapping it into a `std::function`), further problems
can arise when this function is given as a ''function reference''
2024-10-22 03:20:50 +02:00
0de7905444 Invocation: introduce pattern data holder into NodeBuilder
- add an unspecified data holder type into the NodeBuilder
- establish ability to cross-build a `NodeBuilder` with adapted data holder
2024-10-21 04:40:51 +02:00
4a963c9fee Invocation: draft how the 1:1-fallback wiring could work
...and as expected, this turns up quite some inconsistencies,
especially regarding usage of the »buffer types«.

Basically, the `PortBuilder` is responsible for the high-level functionality
and thus must ensure the nested `WiringBuilder` is addressed and parameterised
properly to connect all »slots« of the processing function.
 - can use a helper function in the WiringBuilder to fill in connections
 - but the actual buffer types passed over these connectinos are totally
   unchecked at that level, and can not see yet how this danger can be
   mitigated one level above, where the PortBuilder is used.
 - it is still unclear what a »buffer type« actually means; it could
   be the pointer type, but it could also imply a class or struct type
   to be emplaced into the buffer, which is a special extension to the
   `BufferProvider` protocol, yet seems to be used here rather to transport
   specific data types required by the actual media handling library (e.g. FFmpeg)
2024-10-14 04:07:47 +02:00
4df4ff2792 Invocation: consider minimal test setup and verification
__Analysis__: what kind of verifications are sensible to employ
to cover building, wiring and invocation of render nodes?
Notably, a test should cover requirements and observable functionality,
while ''avoiding direct hard coupling to implementation internals...''

__Draft__: the most simple node builder invocation conceivable...
2024-10-13 03:49:01 +02:00
a02873a015 Invocation: pass the actual processing function
...need to pass a binding for the actual processing function
in a way that it acts as a ''prototype'' — since the `Feed`,
i.e. the ''Invocation Adapter'' must be generated for each
invocation anew within the current stack frame
(so to avoid spurious heap allocations)
2024-10-11 04:39:40 +02:00
9490192ef8 Invocation: integrate WeavingBuilder into PortBuilder
...seems that the former is well suited to serve as detail builder
used internally by the latter to provide a simplified standard adaptation
for a given processing function.

The integration can be achieved to layer a specialised detail builder class
on top, which can be entered only by specifying the concrete function or lambda
to wrap for the processing; the further builder-API-functions to control
the wiring in detail become thus only accessible after the function type
is known; this allows to place the detail builder as member into the
enclosing port builder and thus to allocate everything within the current
stack frame invoking the builder chain.
2024-10-11 02:45:51 +02:00
5f0b8b8a81 Invocation: usage analysis for prototype
...after having determined the several levels of prototyping
currently employed, an important step ahead could be achieved
by analysing the intended and implied usage context of this
builder scheme, while still assuming the simplifications
related to prototyping.

It can be assumed that
 * the Level-2 builder object is ''somehow provided''
 * the invocation happens from within a media-handling lib-plugin
 * alongside with the desired `ProcAsset` spec, an `ExpectationContext`
   will be provided, allowing to pass-through additional semantic tags

The implementation in the lib-plugin is then able to draw from specific
knowledge related to the **Domain Ontology** for ''especially for this library''
and provide the necessary wrappers and parameter mapping information.

⟹ the **Level-2**-builder should thus expose an API to
 * set up a straight forward mapping, based on a given wrapper functor
   to delegate to the actual library invocation
 * allow optionally to override some of the input connections
 * alternatively allow to use a complete `InvocationAdapter`,
   including a `FeedManifold`, as provided directly by the library-plugin
2024-10-10 21:35:02 +02:00
42f8f8d5af Invocation: Prototyping how to setup invocation wiring
...still fighting to find a suitable API to define
how inputs and outputs are connected and mapped to function parameters.

The solution drafted here uses the reshaped `DataBuilder` (≙`lib::SeveralBuilder`)
to add up connections for each »slot«, disregarding the possibility of permutations.
Similar to `NodeBuilder`, a policy template is used to pass down the setup
for an actual custom allocator.
2024-07-24 03:52:44 +02:00
352ef31ab0 Invocation: further condense the allocator-selector definition
After applying all the preceding refactorings, it turns out that
the `DataBuilder` defined here ''is essentially `lib::SeveralBuilder`'',
only with a different arrangement of the type parameters, due to the
specific usage context here.

It is thus possible to replace all the interim / helper / rebinding templates
by simple templated typedefs. The only tangible difference is that for
usage in the Builder, a ''selector policy'' is passed as a simple type argument,
which in practice wires the concrete allocator information down into each
sub-builder created during the ongoing construction of a node structure.
2024-07-23 02:38:06 +02:00
1705c40dc2 Invocation: rearrange SeveralBuilder policy
redefine the policy for `lib::SeveralBuilder` to be a template-template parameter.
In fact it should have been this way from start, yet defining this kind of
very elaborate code bottom-up lets you sometime miss the wood for the trees

So to restate: `lib::SeveralBuilder` takes a ''policy template,''
which then in turn will be instantiated with the same types `I` (interface)
and `E` (element type) used on `SeveralBuilder` itself. Obviously, there can be
further types involved and thus additional type parameters may be necessary,
notably the ''Allocator'' — yet these are better injected when ''defining''
the policy template itself.

The default binding for this policy template is defined as `allo::HeapOwn`,
which causes the builder to allocate the storage extents through the standard
heap allocator, and for the created `lib::Several` to take full ownership of
embedded objects, invoking their destructors when falling out of scope.
2024-07-17 01:43:17 +02:00
2fd3629d80 Invocation: difficulties with defining a suitable DataBuilder
As a direct consequence of the insights regarding Dependency-Injection,
a ''Builder Toolkit'' is required, which can be used to adapt various
kinds of ''Weaving Patterns'' — since obviously it is not possible to
settle down on a single Pattern, and thus several ''families of builders''
will emerge, one for each ''line of construction'' for ''Weaving Patterns''.

To stress this point, what I am coding here is a prototype, aimed at
being used as part of a **Test Domain Ontology** — and other Domain Ontologies
(e.g. für FFmpeg) will certainly require other construction schemes
for their Weaving Patterns. So this is an open field, and can not be
settled once and for all.

This immediately leads to another, rather technical problem:
If we're about to work with ''delegate Builders,'' then also
a way to pass-down the allocator configuration is required.

We had settled on a preliminary solution with the helper `DataBuilder`,
yet this solution looks like it defines how `lib::SeveralBuilder`
should be used in most of the cases. So there is now a conflict
between the existing definition scheme for `lib::SeveralBuilder`,
which was achieved in a bottom-up way, and a slightly different
definition scheme ''as it should be''

Starting to attack this latter detail problem, as a first step,
the definition of `DataBuilder` can be simplified by collapsing
it with the `lib::allo::SetupSeveral`
2024-07-17 02:35:05 +02:00
d09b061434 Invocation: add nested builder to configure a port
...which brings us right into the middle of the task of building a Turnout...
2024-07-08 19:24:03 +02:00
d3344e7dd3 Invocation: improve notation by using a wrapper
...so the solution is to build up the working data as `lib::SeveralBuilder`;
however, a more concise notation can be achieved with a suitably configured
wrapping subclass; together with the cross-builder trick, this allows
to write the allocation configuration in a clearly libelled way,
while the field definition and the builder constructor hides the
complexities of picking up the extension point and passing on the
wiring to the allocator instance.
2024-07-08 05:41:31 +02:00
d291853174 Invocation: add cross-builder to inject a specific (node) allocator
...using the same pattern here as was successful also for the underlying lib::SeveralBuilder;
even if it may seem logically backwards, it just reads much better and
is more understandable, and has the added benefit of providing a dedicated
definition scope, which can be kept separate from the constructor definition
of the actual builder

{{{
  prepareNode()
    .withAllocator<XYZ>()
    .addLead(predecessor)
    .build()
}}}
2024-07-08 04:45:16 +02:00
cedb1830dc Invocation: work out solution for builder initialisation
...turns out to be surprisingly tricky, since the nested
lib::SeveralBuilder instances require parametrisation by a
''policy template,'' which in turn relies on the actual allocator.
And we want to provide the allocator as a constructor parameter,
including the ability to pick up a custom specialisation for
some specific allocator (notably AllocationCluster requires
to hook into this kind of extension point, to be able to
employ its dedicated API for dynamic allocation adjustment)
2024-07-08 03:56:38 +02:00
58a955a879 Invocation: first draft of the node builder invocation 2024-07-06 21:31:03 +02:00
7c554caf08 Invocation: clarify further requirements for the Level-2 builder
...especially what is necessary to represent at this level and what information
is implicit; notably there will be an implicit default wiring, but we allow
for case-by-case deviations
2024-07-06 04:37:36 +02:00
1f7ddbe5ec Invocation: draft possible syntactic structure based on these conjectures
The Builder will have to perform several passes, gradually refining
the model into the low-level Render Node network. Right now, some
guesses regarding the last steps of this process are possible,
thus defining the lowest level of a model builder structure
 * Level-3 : mapping data flow paths
 * Level-2 : detailed configuration of data buffer passing
 * Level-1 : build the actual parameter structures for invocation

In the current »Vertical Slice« we're able to fully define Level-1
and maybe Level-2
2024-07-06 01:28:18 +02:00
ce9bf7f143 Invocation: conjectures pertaining an implementation of Node-Graph generation
To escape a possible deadlock in analysis, I resort to developing
some kind of free-wheeling presupposition how the **Builder** could
be implemented — a centrepiece of the Lumiera architecture envisioned
thus far — which ''unfortunately'' can only be planned and developed
in a more solid way ''after'' the current »Vertical Slice« is completed.

Thus I find myself in the uncomfortable situation of having to work towards
a core piece, which can not yet be built, since it relies heavily on
the very structures to be built...
2024-07-06 01:13:23 +02:00
Renamed from src/steam/engine/node-wiring-builder.hpp (Browse further)