90 #ifndef STEAM_ENGINE_WEAVING_PATTERN_BUILDER_H 91 #define STEAM_ENGINE_WEAVING_PATTERN_BUILDER_H 113 #include <functional> 123 using StrView = std::string_view;
135 using lib::meta::is_BinaryFun;
136 using std::remove_reference_t;
149 static_assert(
_Fun<FUN>() ,
"something funktion-like required");
150 static_assert(is_BinaryFun<FUN>() ,
"function with two arguments expected");
152 using ArgI = remove_reference_t<typename _Fun<FUN>::Args::List::Head>;
153 using ArgO = remove_reference_t<typename _Fun<FUN>::Args::List::Tail::Head>;
158 static_assert(not
sizeof(ARG),
"processing function expected to take array-of-buffer-pointers");
160 template<
class BUF,
size_t N>
186 inline constexpr uint
190 auto constexpr bound = std::max (_F::FAN_I, _F::FAN_O);
191 static_assert (bound <= 10,
192 "Limitation of template instances exceeded");
193 return bound < 3? bound
210 template<
class MAN,
class FUN>
214 using BuffI =
typename _ProcFun<FUN>::BuffI;
215 using BuffO =
typename _ProcFun<FUN>::BuffO;
217 enum{ N = MAN::STORAGE_SIZ
218 , FAN_I = _ProcFun<FUN>::FAN_I
219 , FAN_O = _ProcFun<FUN>::FAN_O
222 static_assert(FAN_I <= N and FAN_O <= N);
224 using ArrayI = std::array<BuffI*, FAN_I>;
225 using ArrayO = std::array<BuffO*, FAN_O>;
233 template<
typename...INIT>
235 : process{forward<INIT> (funSetup)...}
240 connect (uint fanIn, uint fanOut)
242 REQUIRE (fanIn >= FAN_I and fanOut >= FAN_O);
243 for (uint i=0; i<FAN_I; ++i)
244 inParam[i] = & MAN::inBuff[i].
template accessAs<BuffI>();
245 for (uint i=0; i<FAN_O; ++i)
246 outParam[i] = & MAN::outBuff[i].
template accessAs<BuffO>();
252 process (inParam, outParam);
266 template<u
int N,
class FUN>
274 std::function<Feed()> buildFeed;
282 : buildFeed{[=]{
return Feed{fun}; }}
289 template<
class POL,
class I,
class E=I>
293 using SizMark = std::integral_constant<uint,siz>;
307 template<
class PAR,
class BUILD, u
int siz>
313 uint size() {
return 1 + PAR::size(); }
317 collectEntries (DAB& dataBuilder, uint cntElm =0, uint maxSiz =0)
319 PAR::collectEntries (dataBuilder, cntElm+1, max (siz,maxSiz));
320 buildEntry (dataBuilder);
324 PatternData(PAR&& predecessor, BUILD&& entryBuilder)
325 : PAR{move (predecessor)}
326 , buildEntry{move (entryBuilder)}
336 uint size() {
return 0; }
340 collectEntries (DAB& dataBuilder, uint cntElm, uint maxSiz)
342 dataBuilder.reserve (cntElm, maxSiz);
349 template<u
int N,
class FUN>
367 template<
class POL, u
int N,
class FUN>
371 using FunSpec = _ProcFun<FUN>;
373 static constexpr SizMark<sizeof(TurnoutWeaving)> sizMark{};
374 static constexpr uint FAN_I = FunSpec::FAN_I;
375 static constexpr uint FAN_O = FunSpec::FAN_O;
378 using TypeMarker = std::function<BuffDescr(BufferProvider&)>;
382 std::vector<TypeMarker> buffTypes;
383 std::vector<ProviderRef> providers;
393 template<
typename...INIT>
394 WeavingBuilder(FUN&& init, StrView nodeSymb, StrView portSpec, INIT&& ...alloInit)
395 : leadPorts{forward<INIT> (alloInit)...}
396 , nodeSymb_{nodeSymb}
397 , portSpec_{portSpec}
402 attachToLeadPort (
ProcNode& lead, uint portNr)
404 if (leadPorts.size() >= FAN_I)
406 "but all %d »input slots« of the processing function are already connected."}
409 PortRef portRef{lead.getPort (portNr)};
410 leadPorts.
append (portRef);
416 appendBufferTypes (uint cnt)
418 if (buffTypes.size()+cnt > FAN_O)
419 throw err::Logic{
_Fmt{
"Builder: attempt add %d further output buffers, " 420 "while %d of %d possible outputs are already connected."}
421 % cnt % buffTypes.size() % FAN_O
426 ENSURE (buffTypes.size() <= N);
431 fillRemainingBufferTypes()
433 using BuffO =
typename FunSpec::BuffO;
434 uint cnt = FAN_O - buffTypes.size();
435 return appendBufferTypes<BuffO>(cnt);
441 REQUIRE (leadPorts.size() <= FAN_I);
442 uint cnt = FAN_I - leadPorts.size();
443 if (FAN_I > knownLeads.size())
444 throw err::Logic{
_Fmt{
"Builder: attempt to auto-connect %d further »input slots«, " 445 "but this ProcNode has only %d predecessor nodes, while the " 446 "given processing function expects %d inputs."}
447 % cnt % knownLeads.size() % FAN_I
450 attachToLeadPort (knownLeads[leadPorts.size()], defaultPort);
455 selectResultSlot (uint idx)
457 this->resultSlot = idx;
468 maybeFillDefaultProviders (buffTypes.size());
469 REQUIRE (providers.size() == buffTypes.size());
473 for (
auto& typeConstructor : buffTypes)
475 typeConstructor (providers[i++]));
477 ENSURE (leadPorts.size() <= N);
478 ENSURE (leadPorts.size() == FunSpec::FAN_I);
479 ENSURE (outTypes.size() <= N);
480 ENSURE (outTypes.size() == FunSpec::FAN_O);
484 return [leads = move(leadPorts.
build())
485 ,types = move(outTypes.build())
486 ,procFun = move(fun_)
487 ,resultIdx = resultSlot
490 (PortDataBuilder& portData)
mutable ->
void 492 portData.template emplace<TurnoutWeaving> (procID
503 maybeFillDefaultProviders (
size_t maxSlots)
505 for (uint i=providers.size(); i <
maxSlots; ++i)
506 providers.emplace_back (ctx().mem);
SeveralBuilder && reserve(size_t cntElm=1, size_t elmSiz=reqSiz< TY >())
ensure up-front that a desired capacity is allocated
Processing structure to activate a Render Node and produce result data.
Several< I > build()
Terminal Builder: complete and lock the collection contents.
DirectFunctionInvocation(FUN fun)
when building the Turnout, prepare the invocation adapter
Typical base configuration for a Weaving-Pattern chain:
Standard implementation for a Weaving Pattern to connect the input and output data feeds (buffers) in...
Helper to pick up the parameter dimensions from the processing function.
Obsolete, to be rewritten /////TICKET #826.
inline string literal This is a marker type to indicate that
Types marked with this mix-in may be moved but not copied.
A low-level Builder to prepare and adapt for a specific node invocation.
Steam-Layer implementation namespace root.
A front-end for using printf-style formatting.
Access point to singletons and other kinds of dependencies designated by type.
Metadata interface to generate symbolic and hash ID tags for media processing steps.
Adapter to handle a simple yet common setup for media processing.
Fixed standard setup used in each Port of the Render Node to generate data.
static ProcID & describe(StrView nodeSymb, StrView portSpec)
build and register a processing ID descriptor
Derived specific exceptions within Lumiera's exception hierarchy.
Abstraction: Fixed array of elements.
BuffDescr getDescriptor(ARGS ...args)
define a "buffer type" for automatically creating an instance of the template type embedded into the ...
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
constexpr uint manifoldSiz()
Pick a suitable size for the FeedManifold to accommodate the given function.
Builder to create and populate a lib::Several<I>.
Recursive functional data structure to collect weaving pattern data and finally to emplace a Turnout ...
Extension to allow placing objects right into the buffers, taking ownership.
A collection of frequently used helper functions to support unit testing.
Dependency context to hold global parameters and services for the render engine.
Lumiera error handling (C++ interface).
Key abstraction of the Render Engine: A Data processing Node.
Interface: a facility providing and managing working buffers for media calculations.
SeveralBuilder && shrinkFit()
discard excess reserve capacity.
uint maxSlots(0)
number of different registered Types
Data recursion end: prime the port data storage by reserving appropriate storage to hold all known Tu...
SeveralBuilder && append(VAL &&val, VALS &&...vals)
append copies of one or several arbitrary elements
Builder to create and populate instances of the lib::Several container.
Abstraction to represent buffer management and lifecycle within the render engine.