Lumiera  0.pre.03
»edit your freedom«
proc-node.cpp
Go to the documentation of this file.
1 /*
2  ProcNode - Implementation of render node processing
3 
4  Copyright (C)
5  2024, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 * *****************************************************************/
13 
14 
22 #include "steam/engine/proc-id.hpp"
24 #include "lib/iter-explorer.hpp"
25 #include "lib/format-string.hpp"
26 #include "lib/format-util.hpp"
27 #include "lib/util.hpp"
28 
29 #include <boost/functional/hash.hpp>
30 #include <unordered_set>
31 #include <set>
32 
33 
34 namespace steam {
35 namespace engine {
36 
37  using lib::explore;
38  using util::_Fmt;
39  using util::isnil;
40  using util::unConst;
41  using util::contains;
42  using boost::hash_combine;
43 
44  namespace {// Details: registration and symbol table for node spec data...
45 
46  std::unordered_set<ProcID> procRegistry;
47  std::unordered_set<string> symbRegistry;
48 
50  void inline
51  dedupSymbol (StrView& symbol)
52  {
53  auto res = symbRegistry.emplace (symbol);
54  symbol = *res.first;
55  }
56  } // (END) Details...
57 
58 
59 
60  Port::~Port() { }
61 
62 
68  ProcID&
69  ProcID::describe (StrView nodeSymb, StrView portSpec)
70  {
71  REQUIRE (not isnil (nodeSymb));
72  REQUIRE (not isnil (portSpec));
73  REQUIRE (not contains (nodeSymb, ' '));
74  auto p = portSpec.find('(');
75  if (p == string::npos)
76  throw err::Invalid{_Fmt{"Spec for processing operation must contain at least one argument list. "
77  "Node:%s Spec:%s"}
78  % nodeSymb % portSpec
79  };
80  auto res = procRegistry.insert (ProcID{nodeSymb, portSpec.substr(0,p), portSpec.substr(p)});
81  ProcID& entry{unConst (*res.first)};
82  if (res.second)
83  {// new record placed into the registry
84  dedupSymbol (entry.nodeSymb_);
85  dedupSymbol (entry.argLists_);
86  if (not isnil(entry.portQual_))
87  dedupSymbol (entry.portQual_);
88  }
89  return entry;
90  }
91 
93  ProcID::ProcID (StrView nodeSymb, StrView portQual, StrView argLists)
94  : nodeSymb_{nodeSymb}
95  , portQual_{portQual}
96  , argLists_{argLists}
97  { }
98 
104  HashVal
105  hash_value (ProcID const& procID)
106  {
107  HashVal hash = boost::hash_value (procID.nodeSymb_);
108  if (not isnil(procID.portQual_))
109  hash_combine (hash, procID.portQual_);
110  hash_combine (hash, procID.argLists_);
111  return hash;
112  }
113 
114  string
115  ProcID::genProcName()
116  {
117  std::ostringstream buffer;
118  buffer << nodeSymb_;
119  if (not isnil(portQual_))
120  buffer << '.' << portQual_;
121  return buffer.str();
122  }
123 
124  string
126  {
127  std::ostringstream buffer;
128  buffer << nodeSymb_;
129  if (not isnil(portQual_))
130  buffer << '.' << portQual_;
131  buffer << argLists_;
132  return buffer.str();
133  }
134 
135  string
136  ProcID::genNodeName()
137  {
138  return string{nodeSymb_};
139  }
140 
141 
142  namespace { // Helper to access ProcID recursively
143  ProcID&
144  procID (ProcNode& node)
145  {
146  REQUIRE (not isnil(watch(node).ports()));
147  return watch(node).ports().front().procID;
148  }
149  }
150 
151  string
152  ProcID::genNodeSpec (Leads& leads)
153  {
154  std::ostringstream buffer;
155  buffer << nodeSymb_;
156  if (1 != leads.size())
157  buffer << genSrcSpec(leads);
158  else
159  { // single chain....
160  ProcNode& p{leads.front().get()};
161  buffer << "◁—"
162  << procID(p).genNodeName() // show immediate predecessor
163  << procID(p).genSrcSpec(leads); // and behind that recursively the source(s)
164  }
165  return buffer.str();
166  }
167 
168  string
170  {
171  return isnil(leads)? string{"-◎"} // no leads => starting point itself is a source node
172  : "┉┉{"
173  + util::join(
174  explore(leads)
175  .expandAll([](ProcNode& n){ return explore(watch(n).leads()); }) // depth-first expand all predecessors
176  .filter ([](ProcNode& n){ return watch(n).isSrc(); }) // but retain only leafs (≙ source nodes)
177  .transform([](ProcNode& n){ return procID(n).nodeSymb_;}) // render the node-symbol of each src
178  .deduplicate()) // sort and deduplicate
179  + "}";
180  }
181 
182 
183 
189  string
191  {
192  REQUIRE (not isnil(ports()));
193  return ports().front().procID.genNodeSpec (leads());
194  }
195 
196  HashVal
198  {
199  UNIMPLEMENTED ("calculate an unique hash-key to designate this node");
200  }
201 
206  string
208  {
209  auto& p{n_.wiring_.ports};
210  return portIdx < p.size()? p[portIdx].procID.genProcSpec()
211  : util::FAILURE_INDICATOR;
212  }
213 
214  HashVal
216  {
217  UNIMPLEMENTED ("calculate an unique, stable and reproducible hash-key to identify the Turnout");
218  }
219 
220 
221 }} // namespace steam::engine
virtual ~Port()
this is an interface
Definition: proc-node.cpp:60
HashVal getNodeHash()
calculate an unique hash-key to designate this node
Definition: proc-node.cpp:197
friend HashVal hash_value(ProcID const &)
generate registry hash value based on the distinct data in ProcID.
Definition: proc-node.cpp:105
auto explore(IT &&srcSeq)
start building a IterExplorer by suitably wrapping the given iterable source.
string getNodeSpec()
generate a descriptive Spec of this ProcNode for diagnostics
Definition: proc-node.cpp:190
bool filter(Placement< DummyMO > const &candidate)
a filter predicate to pick some objects from a resultset.
AnyPair entry(Query< TY > const &query, typename WrapReturn< TY >::Wrapper &obj)
helper to simplify creating mock table entries, wrapped correctly
Front-end for printf-style string template interpolation.
HashVal getPortHash(uint portIdx)
calculate an unique, stable and reproducible hash-key to identify the Turnout
Definition: proc-node.cpp:215
Steam-Layer implementation namespace root.
A front-end for using printf-style formatting.
Metadata interface to generate symbolic and hash ID tags for media processing steps.
static ProcID & describe(StrView nodeSymb, StrView portSpec)
build and register a processing ID descriptor
Definition: proc-node.cpp:69
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
ProcID(StrView nodeSymb, StrView portQual, StrView argLists)
Definition: proc-node.cpp:93
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
string getPortSpec(uint portIdx)
generate a descriptive diagnostic Spec for the designated Turnout
Definition: proc-node.cpp:207
Interface to the processing nodes and the render nodes network.
void dedupSymbol(StrView &symbol)
deduplicate and re-link to the entry in the symbol table
Definition: proc-node.cpp:51
size_t HashVal
a STL compatible hash value
Definition: hash-value.h:52
Key abstraction of the Render Engine: A Data processing Node.
Definition: proc-node.hpp:154
Collection of small helpers and convenience shortcuts for diagnostics & formatting.
Building tree expanding and backtracking evaluations within hierarchical scopes.
string genProcSpec()
render a descriptor for the operation (without predecessors)
Definition: proc-node.cpp:125
HashVal hash_value(ProcID const &procID)
generate registry hash value based on the distinct data in ProcID.
Definition: proc-node.cpp:105
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255
string genSrcSpec(Leads &)
transitively enumerate all unique source nodes
Definition: proc-node.cpp:169