Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
node-builder.hpp
Go to the documentation of this file.
1/*
2 NODE-BUILDER.hpp - Setup of render nodes connectivity
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6 2024, Hermann Vosseler <Ichthyostega@web.de>
7
8  **Lumiera** is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the
10  Free Software Foundation; either version 2 of the License, or (at your
11  option) any later version. See the file COPYING for further details.
12
13*/
14
117#ifndef ENGINE_NODE_BUILDER_H
118#define ENGINE_NODE_BUILDER_H
119
120
121#include "lib/error.hpp"
122#include "lib/nocopy.hpp"
129#include "lib/format-string.hpp"
130#include "lib/index-iter.hpp"
131
132#include <utility>
133#include <vector>
134
135
136namespace steam {
137namespace engine {
138 namespace err = lumiera::error;
139
140 using util::_Fmt;
141 using std::forward;
142 using std::move;
143 using std::ref;
144
145
146 namespace { // default policy configuration to use heap allocator
147
149 {
150 template<class I, class E=I>
152 };
153 //
154 }//(End) policy
155
156
157
163 template<class POL, class I, class E=I>
165
166
167
168 template<class POL, class DAT>
169 class NodeBuilder;
170
171 template<class POL, class DAT>
172 class PortBuilderRoot;
173
174
175
176
188 template<class POL, class DAT = PatternDataAnchor>
191 {
194
195 protected:
199
200 public:
201 template<typename...INIT>
202 NodeBuilder (StrView nodeSymbol, INIT&& ...alloInit)
203 : symbol_{nodeSymbol}
204 , leads_{forward<INIT> (alloInit)...}
205 { }
206
207 template<class BUILD, uint siz, class D0>
208 NodeBuilder (NodeBuilder<POL,D0>&& pred, SizMark<siz>, BUILD&& entryBuilder)
209 : symbol_{pred.symbol_}
210 , leads_{move (pred.leads_)}
211 , patternData_{move (pred.patternData_), forward<BUILD> (entryBuilder)}
212 { }
213
214 template<class P, class D0>
215 friend class NodeBuilder;
216
217
219 addLead (ProcNode const& lead)
220 {
221 leads_.append (ref(lead));
222 return move(*this);
223 }
224
225
228
229
245 template<template<typename> class ALO =std::void_t, typename...INIT>
246 auto
247 withAllocator (INIT&& ...alloInit)
248 {
249 using AllocatorPolicy = lib::allo::SetupSeveral<ALO,INIT...>;
250 return NodeBuilder<AllocatorPolicy>{symbol_, forward<INIT>(alloInit)...};
251 }
252
253
254 /************************************************************/
259 {
260 PortData ports;
261 patternData_.collectEntries(ports);
262 return Connectivity{ports.build()
263 ,leads_.build()
264 };
265 }
266 };
267
269 template<class POL, class D0, uint siz, class BUILD>
271
272
273
274
279 template<class POL, class DAT>
281 : protected NodeBuilder<POL,DAT>
282 {
283 public:
286 {
287 static_assert(not sizeof(POL),
288 "can not build a port without specifying a processing function");
289 }
290
293 template<typename FUN>
294 auto invoke (StrView portSpec, FUN fun);
295
298 template<class SPEC>
299 auto computeParam(SPEC&&);
300
301
302 private:
304 : NodeBuilder<POL,DAT>{move(anchor)}
305 { }
306
308 };
309
317 template<class POL, class DAT>
320 {
321 return PortBuilderRoot<POL,DAT>{move(*this)};
322 }
323
324
325
334 template<class POL, class DAT, class WAB>
336 : public PortBuilderRoot<POL,DAT>
337 {
339
342
343 public:
344
349 template<class ILA, typename...ARGS>
351 createBuffers (ARGS&& ...args)
352 {
353 UNIMPLEMENTED ("define builder for all buffers to use");
354 return move(*this);
355 }
356
357
362 {
363 weavingBuilder_.selectResultSlot(r);
364 return move(*this);
365 }
366
375 {
376 return connectLeadPort (idx, this->defaultPort_);
377 }
378
382 {
383 return connectLeadPort (leadNode, this->defaultPort_);
384 }
385
389 {
390 if (idx >= _Par::leads_.size())
391 throw err::Logic{_Fmt{"Builder refers to lead-node #%d, yet only %d are currently defined."}
392 % idx % _Par::leads_.size()
393 ,LERR_(INDEX_BOUNDS)
394 };
395 weavingBuilder_.attachToLeadPort (_Par::leads_[idx], port);
396 return move(*this);
397 }
398
401 connectLeadPort (ProcNode& leadNode, uint port)
402 {
403 uint knownEntry{0};
404 for (auto& lead : lib::IndexIter{_Par::leads_}) // leads_ holds ref-wrappers
405 if (util::isSameObject (leadNode, lead.get()))
406 break;
407 else
408 ++knownEntry;
409 if (knownEntry == _Par::leads_.size())
410 _Par::addLead (leadNode);
411
412 ENSURE (knownEntry < _Par::leads_.size());
413 return connectLeadPort (knownEntry, port);
414 }
415
418 useLeadPort (uint defaultPort)
419 {
420 this->defaultPort_ = defaultPort;
421 return move(*this);
422 }
423
431 template<class PFX>
432 auto
433 attachParamFun (PFX paramFunctor)
434 {
435 using AdaptedWeavingBuilder = WAB::template Adapted<PFX>;
436 using AdaptedPortBuilder = PortBuilder<POL,DAT,AdaptedWeavingBuilder>;
437 //
438 return AdaptedPortBuilder{move(*this)
439 ,weavingBuilder_.adaptParam (move (paramFunctor))
440 };
441 }
442
444 template<class AUTO>
445 auto
446 attachAutomation (AUTO&& aFun)
447 {
448 return attachParamFun ([automation = forward<AUTO>(aFun)]
449 (TurnoutSystem& turnoutSys)
450 {
451 return automation (turnoutSys.getNomTime());
452 });
453 }
454
456 template<typename PAR>
457 auto
458 setParam (PAR paramVal)
459 {
460 return attachParamFun ([=](TurnoutSystem&) -> PAR
461 {
462 return paramVal;
463 });
464 }
465
466 template<typename PAR, typename...PARS>
467 auto
468 setParam (PAR v1, PARS ...vs)
469 {
470 return attachParamFun ([=](TurnoutSystem&) -> tuple<PAR,PARS...>
471 {
472 return std::make_tuple (v1,vs...);
473 });
474 }
475
478 template<typename GET>
479 auto
480 retrieveParam (GET&& getter)
481 {
482 return attachParamFun ([accessor=forward<GET>(getter)]
483 (TurnoutSystem& turnoutSys)
484 {
485 return turnoutSys.get(accessor);
486 });
487 }
488
489 template<typename ADA>
490 auto
491 adaptParam (ADA&& paramAdaptor)
492 {
493 using DecoratedPrototype = WAB::template Decorated<ADA>;
494 using AdaptedPortBuilder = PortBuilder<POL,DAT,DecoratedPrototype>;
495 //
496 return AdaptedPortBuilder{move(*this)
497 ,weavingBuilder_.adaptProcFunParam (move (paramAdaptor))
498 };
499 }
500
504 template<typename PAR, typename...PARS>
505 auto
506 closeParamFront (PAR v1, PARS ...vs)
507 {
508 return adaptParam(
509 WAB::ParamClosure::template closeFront (forward<PAR> (v1)
510 ,forward<PARS>(vs)...));
511 }
512
515 template<typename PAR, typename...PARS>
516 auto
517 closeParamBack (PAR v1, PARS ...vs)
518 {
519 return adaptParam(
520 WAB::ParamClosure::template closeBack (forward<PAR> (v1)
521 ,forward<PARS>(vs)...));
522 }
523
527 template<size_t idx, typename PAR>
528 auto
529 closeParam (PAR val)
530 {
531 return adaptParam(
532 WAB::ParamClosure::template close<idx> (forward<PAR> (val)));
533 }
534
535
536
537 /*************************************************************/
543 auto
545 {
546 weavingBuilder_.connectRemainingInputs (_Par::leads_, this->defaultPort_);
547 return NodeBuilder{static_cast<NodeBuilder<POL,DAT>&&> (*this) // slice away PortBulder subclass data
548 ,weavingBuilder_.sizMark
550 } // chain to builder with extended patternData
551
552 private:
553 template<typename FUN>
554 PortBuilder(_Par&& base, FUN&& fun, StrView portSpec)
555 : _Par{move(base)}
556 , weavingBuilder_{forward<FUN> (fun), _Par::symbol_, portSpec, _Par::leads_.policyConnect()}
558 { } // ^^^ by default use next free port
559
560 friend class PortBuilderRoot<POL,DAT>;
561
563 template<class WABO>
564 PortBuilder (PortBuilder<POL,DAT,WABO>&& prevBuilder, WAB&& adaptedWeavingBuilder)
565 : _Par{move(prevBuilder)}
566 , weavingBuilder_{move (adaptedWeavingBuilder)}
567 , defaultPort_{prevBuilder.defaultPort_}
568 { }
569
570 template<class PX, class DX, class WX>
571 friend class PortBuilder;
572 };
573
574
596 template<class POL, class DAT>
597 template<typename FUN>
598 auto
600 {
601 using Prototype = FeedManifold<FUN>::Prototype;
602 using WeavingBuilder_FUN = WeavingBuilder<POL, Prototype>;
603 return PortBuilder<POL,DAT, WeavingBuilder_FUN>{move(*this), move(fun), portSpec};
604 }
605
606
607
608
609
618 template<class POL, class DAT, class SPEC>
620 : public PortBuilderRoot<POL,DAT>
621 {
623
624 using BlockBuilder = SPEC::BlockBuilder;
625 using PostProcessor = function<void(TurnoutSystem&)>;
626
631
632 public:
641 {
642 return delegateLeadPort (idx, defaultPortNr_);
643 }
644
648 {
649 return delegateLeadPort (leadNode, defaultPortNr_);
650 }
651
655 {
656 if (idx >= _Par::leads_.size())
657 throw err::Logic{_Fmt{"Builder refers to lead-node #%d, yet only %d are currently defined."}
658 % idx % _Par::leads_.size()
659 ,LERR_(INDEX_BOUNDS)
660 };
661 ProcNode& leadNode = _Par::leads_[idx];
662 delegatePort_ = & leadNode.getPort (port);
663 return move(*this);
664 }
665
670 {
671 uint knownEntry{0};
672 for (auto& lead : lib::IndexIter{_Par::leads_})
673 if (util::isSameObject (leadNode, lead))
674 break;
675 else
676 ++knownEntry;
677 if (knownEntry == _Par::leads_.size())
678 _Par::addLead (leadNode);
679
680 ENSURE (knownEntry < _Par::leads_.size());
681 return delegateLeadPort (knownEntry, port);
682 }
683
684
696 {
697 postProcessor_ = move(pp);
698 }
699
700
701 /*********************************************************************/
706 auto
708 {
709 if (not delegatePort_)
710 throw err::Logic{"Building a ParamAgentNode requires a delegate node "
711 "to perform within the scope with extended parameters"
712 ,LERR_(BOTTOM_VALUE)};
713 string portSpec = "Par+"+delegatePort_->procID.genProcSpec();
714 ProcAttrib flags;
715 flags.isProxy = true;
716 flags.manifold = false;
717
718 using WeavingPattern = ParamWeavingPattern<SPEC>;
719 using TurnoutWeaving = Turnout<WeavingPattern>;
720 using PortDataBuilder = DataBuilder<POL, Port>;
721
722 return NodeBuilder ( static_cast<NodeBuilder<POL,DAT>&&> (*this) // slice away PortBulder subclass data
723 , SizMark<sizeof(TurnoutWeaving)>{}
724 ,// prepare a builder-λ to construct the actual Turnout-object
725 [&procID = ProcID::describe(_Par::symbol_,portSpec,flags)
726 ,builder = move(blockBuilder_)
727 ,postProc = move(postProcessor_)
728 ,delegate = delegatePort_
729 ]
730 (PortDataBuilder& portData) mutable -> void
731 {
732 portData.template emplace<TurnoutWeaving> (procID
733 ,move(builder)
734 ,move(postProc)
735 ,*delegate
736 );
737 });
738 } // chain back up to Node-Builder with extended patternData
739
740 private:
742 : _Par{move(base)}
743 , blockBuilder_{move(builder)}
744 , delegatePort_{nullptr}
746 { } // ^^^ by default use next free port
747
748 friend class PortBuilderRoot<POL,DAT>;
749 };
750
751
782 template<class POL, class DAT>
783 template<class SPEC>
784 auto
786 {
787 using ParamBuildSpec = std::decay_t<SPEC>;
788 ParamBuildSpec spec {forward<SPEC>(ref)}; // consumes the spec
789 return ParamAgentBuilder<POL,DAT,ParamBuildSpec>{move(*this), spec.makeBlockBuilder()};
790 }
791
792
793
794
801 inline auto
802 prepareNode (StrView nodeSymbol)
803 {
804 return NodeBuilder<UseHeapAlloc>{nodeSymbol};
805 }
806
807
808
809
810
813 {
814 public:
815
816 void
818 {
819 UNIMPLEMENTED ("enumerate all source feeds required");
820// return move(*this);
821 }
822
823 void
824 retrieve (void* streamType)
825 {
826 (void)streamType;
827 UNIMPLEMENTED ("recursively define a predecessor feed");
828// return move(*this);
829 }
830
831 /****************************************************/
834 void
836 {
837 UNIMPLEMENTED("Level-3 build-walk");
838 }
839 };
840
841
844 {
845 public:
846
847 void
848 from (void* procAsset)
849 {
850 (void)procAsset;
851 UNIMPLEMENTED ("recursively enter definition of processor node to produce this feed link");
852// return move(*this);
853 }
854 };
855
856
857
861 inline auto
862 retrieve(void* streamType)
863 {
864 (void)streamType;
865 UNIMPLEMENTED("start a connectivity definition at Level-3");
866 return LinkBuilder{};
867 }
868
869
870}} // namespace steam::engine
871#endif /*ENGINE_NODE_BUILDER_H*/
Subscript-index based access to a container, packaged as iterator.
Builder to create and populate a lib::Several<I>.
Interface: Description of the input and output ports, processing function and predecessor nodes for a...
void from(void *procAsset)
Top-level builder to create a single Render Node.
PortBuilderRoot< POL, DAT > preparePort()
recursively enter detailed setup of a single processing port
DataBuilder< POL, Port > PortData
NodeBuilder && addLead(ProcNode const &lead)
DataBuilder< POL, ProcNodeRef > LeadRefs
NodeBuilder(NodeBuilder< POL, D0 > &&pred, SizMark< siz >, BUILD &&entryBuilder)
NodeBuilder(StrView nodeSymbol, INIT &&...alloInit)
Connectivity build()
Terminal: complete the ProcNode Connectivity defined thus far.
auto withAllocator(INIT &&...alloInit)
cross-builder function to specify usage of a dedicated node allocator
Nested sub-Builder analogous to PortBuilder, but for building a »Param Agent Node«.
ParamAgentBuilder && delegateLeadPort(uint idx, uint port)
use a lead node and specific port as delegate to invoke with extended parameters
ParamAgentBuilder && installPostProcessor(PostProcessor pp)
Install a post-processing function for the parameters.
auto completePort()
Terminal: complete the Param-Agent wiring and return to the node level.
ParamAgentBuilder && delegateLead(uint idx)
use a lead node designated by ID as delegate to invoke with the extended parameters.
ParamAgentBuilder && delegateLeadPort(ProcNode &leadNode, uint port)
use the specific port on the given node as delegate, while possibly also registering it as lead node.
function< void(TurnoutSystem &)> PostProcessor
ParamAgentBuilder(_Par &&base, BlockBuilder &&builder)
ParamAgentBuilder && delegateLead(ProcNode &leadNode)
use the given node as delegate, but also possibly register it as lead node
Nested DSL builder scope to define a single Port for the enclosing Node.
NodeBuilder< POL, DAT > completePort()
PortBuilderRoot(NodeBuilder< POL, DAT > &&anchor)
friend PortBuilderRoot NodeBuilder()
auto computeParam(SPEC &&)
setup a »ParamAgentNode« to compute additional parameters and then delegate into an existing node inv...
auto invoke(StrView portSpec, FUN fun)
setup standard wiring to adapt the given processing function.
Nested DSL-Builder context to define a regular media processing Port.
auto attachParamFun(PFX paramFunctor)
Embed the explicitly given parameter-functor into the FeedPrototype, so that it will be called on eac...
PortBuilder(PortBuilder< POL, DAT, WABO > &&prevBuilder, WAB &&adaptedWeavingBuilder)
cross-builder to adapt embedded WeavingBuilder type
auto setParam(PAR v1, PARS ...vs)
auto completePort()
Terminal: complete the Port wiring and return to the node level.
PortBuilder && connectLead(ProcNode &leadNode)
connect the next input slot to either existing or new lead-node"
auto closeParamFront(PAR v1, PARS ...vs)
immediately close (≙ fix) some values in a parameter tuple, starting from left, while leaving the rem...
auto closeParamBack(PAR v1, PARS ...vs)
immediately close the rightmost parameter positions, applying the given values in forward order.
auto retrieveParam(GET &&getter)
retrieve the parameter(s) at invocation time through a getter functor, which is typically constructed...
auto closeParam(PAR val)
immediately close a single parameter at designated position
auto attachAutomation(AUTO &&aFun)
control parameter(s) by an automation function, based on nominal timeline time
PortBuilder && useLeadPort(uint defaultPort)
use given port-index as default for all following connections
auto adaptParam(ADA &&paramAdaptor)
PortBuilder && connectLeadPort(uint idx, uint port)
connect next input to lead-node, using a specific port-number
PortBuilder && connectLeadPort(ProcNode &leadNode, uint port)
connect next input to existing or new lead-node, with given port-number
PortBuilder && asResultSlot(uint r)
define the output slot number to use as result
PortBuilder && createBuffers(ARGS &&...args)
PortBuilder(_Par &&base, FUN &&fun, StrView portSpec)
auto setParam(PAR paramVal)
embed a fixed value to use for the parameter(s)
PortBuilder && connectLead(uint idx)
connect the next input slot to existing lead-node given by index
void retrieve(void *streamType)
void build()
Terminal: trigger the Level-3 build walk to produce a ProcNode network.
string genProcSpec() const
render a descriptor for the operation (without predecessors)
static ProcID & describe(StrView nodeSymb, StrView portSpec, ProcAttrib extAttrib=ProcAttrib{})
build and register a processing ID descriptor
Key abstraction of the Render Engine: A Data processing Node.
Port & getPort(uint portIdx)
Communication hub to coordinate and activate the »Render Node Network« performance.
auto & get(ACC const &getter)
get parameter from extension block, as configured by the provided getter functor
Processing structure to activate a Render Node and produce result data.
Definition turnout.hpp:117
Types marked with this mix-in may be moved but not copied.
Definition nocopy.hpp:50
A front-end for using printf-style formatting.
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
Front-end for printf-style string template interpolation.
Iterator-style access handle to a referred container with subscript index.
unsigned int uint
Definition integral.hpp:29
Construction set to assemble and operate a data processing scheme within a Render Node.
AllocationPolicy< I, E, std::allocator > HeapOwn
Default configuration to use heap memory for lib::Several.
Extension point: how to configure the SeveralBuilder to use an allocator ALO, initialised by ARGS.
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
auto prepareNode(StrView nodeSymbol)
Entrance point for building actual Render Node Connectivity (Level-2)
std::integral_constant< uint, siz > SizMark
auto retrieve(void *streamType)
Entrance point for defining data flows and processing steps.
std::string_view StrView
Definition proc-id.hpp:82
Steam-Layer implementation namespace root.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
Definition util.hpp:421
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Construction kit to establish a set of parameters pre-computed prior to invocation of nested nodes.
Interface to the processing nodes and the Render Nodes network.
Builder to create and populate instances of the lib::Several container.
FeedPrototype< FUN > Prototype
cross-builder: Prototype can be used to attach parameter-provider-functors and then to create several...
Specification record for the setup of a »Param Agent Node«.
Implementation for a Weaving Pattern to conduct extended parameter evaluation.
Extended Attributes for ProcID metadata.
Definition proc-id.hpp:96
A low-level Builder to prepare and adapt for a specific node invocation.
Fixed standard setup used in each Port of the Render Node to generate data.
Construction kit to establish an invocation scheme for media calculations.