HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEP_MicroNode.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: DEP_MicroNode.h (DEP Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __DEP_MICRONODE_H_INCLUDED__
12 #define __DEP_MICRONODE_H_INCLUDED__
13 
14 #include "DEP_API.h"
15 #include "DEP_ContextOptions.h"
16 #include <UT/UT_Array.h>
17 #include <UT/UT_ArraySet.h>
18 #include <UT/UT_ConcurrentVector.h>
19 #include <UT/UT_Function.h>
20 #include <UT/UT_IntArray.h>
21 #include <UT/UT_NonCopyable.h>
22 #include <UT/UT_SmallObject.h>
23 #include <UT/UT_StringHolder.h>
24 #include <UT/UT_TBBSpinLock.h>
25 #include <UT/UT_ValArray.h>
26 #include <SYS/SYS_Inline.h>
27 #include <SYS/SYS_Math.h>
28 #include <SYS/SYS_Types.h>
29 #include <iosfwd>
30 
32 
34 
35 /// Propagation info for a dep micro node
37 {
38 public:
39  DEP_PropagateData() { myExprChange = false; }
40  ~DEP_PropagateData() = default;
41 
43 
44  void setExprChange(bool expr_change)
45  { myExprChange = expr_change; }
46  bool isExprChange() const
47  { return myExprChange; }
48 
49 protected:
50  bool myExprChange:1; // a parm expr modification?
51 };
52 
53 /// Represent an atomic unit of computation for dependency tracking.
54 ///
55 /// DEP_MicroNode's form a dependency graph that are connected both implicitly
56 /// and explicitly. The base class maintains the explicit edges while
57 /// subclasses maintain the implicit edges by overriding the
58 /// getInputs()/getOutputs() methods.
59 ///
60 class DEP_API DEP_MicroNode : public UT_SmallObject<DEP_MicroNode>
61 {
62 public:
63  DEP_MicroNode();
64  virtual ~DEP_MicroNode();
65 
67 
68  virtual const char * className() const
69  { return "DEP_MicroNode"; }
70 
71  /// Get list of all our non-null inputs, both implicit and explicit.
72  /// The base class returns the list of explicit inputs.
73  virtual void getInputs(DEP_MicroNodeList &inputs) const;
74 
75  /// Clear all inputs, including any state data related to them. Default
76  /// implementation just calls clearExplicitInputs() and
77  /// setTimeDependent(false).
78  virtual void clearInputs();
79 
80  /// Get list of all our non-null outputs, both implicit and explicit.
81  /// The base class returns the list of explicit outputs.
82  virtual void getOutputs(DEP_MicroNodeList &outputs) const;
83 
84  /// update() is used by users of micro-nodes to mark this node as clean at
85  /// the given time t. By default, it simply marks it as no longer dirty but
86  /// subclasses override this to do more work.
87  virtual void update(fpreal t)
88  { setDirty(false); }
89 
90  /// requiresUpdate() specifies if the micro-node was dirtied, possibly
91  /// based on the time t. By default, it returns isDirty() but subclasses
92  /// override this to handle other conditions that make this micro-node
93  /// requiring an update.
94  virtual bool requiresUpdate(fpreal t) const
95  { return isDirty(); }
96 
97  /// Methods for manipulating explicit edges
98  // @{
99 
100  /// Add an input that this micronode depends on, with control on whether to
101  /// check for duplicates.
102  void addExplicitInput(
103  DEP_MicroNode &inp,
104  bool check_dup);
105 
106  /// Add an input that this micronode depends on
108  { addExplicitInput(inp, /*check_dup*/true); }
109 
110  /// Bulk add multiple explicit inputs at once
111  void addExplicitInputs(
112  const DEP_MicroNodeList &sources,
113  bool check_dup = true);
114 
115  /// Get list of all non-null explicit inputs
116  void getExplicitInputs(
117  DEP_MicroNodeList &inputs) const;
118 
119  /// Get the number of non-null inputs
121  { return countEdges(myExplicitInputs); }
122 
123  /// Get list of all non-null explicit outputs
124  void getExplicitOutputs(
125  DEP_MicroNodeList &outputs) const;
126 
127  /// Get the number of non-null outputs
129  { return countEdges(myExplicitOutputs); }
130 
131  // @}
132 
133  typedef UT_Function<
134  void (DEP_MicroNode & /*micronode*/,
135  DEP_MicroNode & /*src*/)
137  typedef UT_Function<
138  bool (const DEP_MicroNode & /*micronode*/,
139  const DEP_MicroNode & /*src*/)
141 
142  /// Mark this micronode and all its dependents as dirty. The global dirty
143  /// counter will be incremented once for each call to propagateDirty().
144  ///
145  /// @param client_visit Called for each micronode that is dirtied
146  /// @param only_outputs If true, then *this is ommitted from being
147  /// dirtied
148  ///
149  /// @note This method is NOT thread-safe with *any* operation on *any*
150  /// micronode. Only call this when no other micronode operations are
151  /// running.
152  void propagateDirty(
153  Visitor client_visit,
154  bool only_outputs = false);
155 
156  /// Callbacks for what to do when the micronode becomes dirty.
157  /// Derived micronodes can override this. Note that it requires
158  /// knowledge of who made it dirty as they may behave differently.
159  /// Currently used by OP_Node::propagateDirtyMicroNode
161  const DEP_PropagateData &propdata)
162  { }
163 
164 
165  /// Traverse all ancestor inputs of this micronode
166  void traverseAncestorInputs(
167  const TraverseVisitor &visitor) const;
168 
169  /// Mark this micronode as having seen the given global dirty counter.
170  /// Returns false if we've already seen it.
171  bool markVisitPass(int pass)
172  {
173  if (myLastVisitPass == pass)
174  return false;
175  myLastVisitPass = pass;
176  return true;
177  }
178 
180  int lastVisitPass() const
181  { return myLastVisitPass; }
182 
183  /// Obtain approximate memory usage
184  virtual int64 getMemoryUsage(bool inclusive) const;
185 
186  /// Dump contents to output stream, strictly for debugging purposes
187  virtual void dump(
188  std::ostream &os,
189  const char *prefix = 0,
190  int indent_level = 0) const;
191  /// Dump the contents is a manner more suitable for DOT.
192  void dumpAsDOT(
193  std::ostream &os,
194  const char *prefix = 0,
195  int indent_level = 0) const;
196 
197  /// Set time dependent flag if any explicit inputs are set.
198  /// Returns true if any explicit inputs are true.
199  bool inheritTimeDependentFromExplicitInputs();
200 
201  /// Set time interested flag if any explicit inputs are set.
202  /// Returns true if any explicit inputs are true.
203  bool inheritTimeInterestedFromExplicitInputs();
204 
205  /// Inherit extra dependencies from all explicit inputs.
206  /// The ignore_deps string array MUST BE SORTED.
207  /// Returns true if any extra dependencies are found.
208  bool inheritContextOptionDepsFromExplicitInputs(
209  const UT_StringArray &ignore_deps);
210 
211  /// Flag accessors
212  // @{
214  bool isDirty() const
215  { return myDirty; }
216  void setDirty(bool flag, bool allow_clear=true)
217  {
218  myDirty = flag;
219  if (allow_clear
220  && myDirty
221  && canClearDependencies())
222  {
223  clearInputs();
224  }
225  }
226 
228  bool isTimeDependent() const
229  { return myTimeDependent; }
231  void setTimeDependent(bool time_dependent)
232  { myTimeDependent = time_dependent; }
233 
235  bool isTimeInterested() const
236  { return myTimeInterested; }
238  void setTimeInterested(bool time_interested)
239  { myTimeInterested = time_interested; }
240 
242  bool hasContextOptionDeps() const
243  { return myContextOptionDeps &&
244  !myContextOptionDeps->empty(); }
248  myContextOptionDeps); }
251  const DEP_ContextOptionDeps &opts)
252  { if (opts.empty()) return;
254  myContextOptionDeps,
255  &myContextOptionDepsLock).insert(
256  opts.begin(), opts.end()); }
259  { if (!opt.isstring()) return;
261  myContextOptionDeps,
262  &myContextOptionDepsLock).
263  insert(opt); }
267  myContextOptionDepsLock);
268  myContextOptionDeps.reset(); }
269 
271  bool isOpDataMicroNode() const
272  { return myIsOPDataMicroNode; }
273 
274  // @}
275 
276  /// Global control whether dependencies can be cleared.
277  static SYS_FORCE_INLINE
279  { return (theKeepDependenciesCount == 0); }
280 
281  /// Global control whether we can evaluate exports
282  static SYS_FORCE_INLINE
284  { return (theBlockEvaluateExports == 0); }
285 
286  /// One true method to compare equality of time values for caching.
287  /// This particular form originates from what OP_Node::cook() did from the
288  /// dawn of time.
290  { return SYSequalZero(a - b); }
291 
292 protected:
293  /// These methods are overriden by subclasses to be used by the
294  /// dirty propagation algorithm.
295  /// @{
296 
297  /// Used to determine if a micronode is currently evaluating. If this
298  /// returns true, during dirty propagation, it will prevent dependencies
299  /// from being removed from it.
300  virtual bool isEvaluating() const
301  { return false; }
302 
303  /// evaluateExports() is called after isExporting() is noted to be true
304  /// during a dirty propagation pass initiated by dirtySubtree().
305  virtual void evaluateExports() { }
306 
307  /// Used to determine if a micronode requires its exports to be evaluated
308  /// during the propagation pass.
309  virtual bool isExporting() const
310  { return false; }
311 
312  /// @}
313 
315  void setIsOpDataMicroNode( bool b )
316  { myIsOPDataMicroNode = b; }
317 
318 private:
319  typedef UT_TBBSpinLock EdgeLock;
320  typedef UT_TBBSpinLock::Scope EdgeLockScope;
321 
322  typedef UT_Array<DEP_MicroNode *> MicroNodeInputPtrVector;
323  typedef UT_ConcurrentVector<DEP_MicroNode *> MicroNodeOutputPtrVector;
324  typedef UT_ArraySet<DEP_MicroNode*> MicroNodePtrSet;
325 
326  void clearExplicitInputs();
327  void clearExplicitOutputs();
328 
329  void compactExplicitInputsAndOutputs();
330 
331  static void compactVector(
332  MicroNodeOutputPtrVector &vec);
333  static void compactVector(
334  MicroNodeInputPtrVector &vec);
335 
336  template <typename MICRONODE_ARRAY>
337  static void getEdgeList(
338  const MICRONODE_ARRAY &edges,
339  DEP_MicroNodeList &micronodes);
340  template <typename MICRONODE_ARRAY>
341  static int countEdges(const MICRONODE_ARRAY &edges);
342 
343 private:
344 
345  /// The list of explicit edges for micronodes
346  // @{
347  EdgeLock myExplicitInputsLock;
348  MicroNodeInputPtrVector myExplicitInputs;
349  MicroNodePtrSet myExplicitInputsSet;
350  MicroNodeOutputPtrVector myExplicitOutputs;
351  // @}
352 
353  DEP_ContextOptionDepsLock myContextOptionDepsLock;
354  DEP_ContextOptionDepsPtr myContextOptionDeps;
355  int myLastVisitPass;
356 
357  bool myDirty;
358  bool myTimeDependent;
359  bool myTimeInterested;
360  bool myIsOPDataMicroNode;
361 
362  static int theKeepDependenciesCount;
363  static int theBlockEvaluateExports;
364 
365  friend class dep_Visitor;
368 };
369 
370 /// Global control whether dependencies can be cleared.
372 {
373 public:
375  { ++DEP_MicroNode::theKeepDependenciesCount; }
377  { --DEP_MicroNode::theKeepDependenciesCount; }
379 };
380 
381 /// Global control whether we can evaluate exports
383 {
384 public:
386  { ++DEP_MicroNode::theBlockEvaluateExports; }
388  { --DEP_MicroNode::theBlockEvaluateExports; }
390 };
391 
392 ///////////////////////////////////////////////////////////////////////////////
393 // Inline Implementations
394 //
395 
396 template <typename MICRONODE_ARRAY>
397 /* static */
398 int
399 DEP_MicroNode::countEdges(const MICRONODE_ARRAY &edges)
400 {
401  int count = 0;
402  for (DEP_MicroNode *e : edges)
403  {
404  if (e)
405  count++;
406  }
407  return count;
408 }
409 
410 #endif // __DEP_MICRONODE_H_INCLUDED__
SYS_FORCE_INLINE void setTimeDependent(bool time_dependent)
Flag accessors.
UT_UniquePtr< DEP_ContextOptionDeps > DEP_ContextOptionDepsPtr
virtual void becameDirty(DEP_MicroNode &src, const DEP_PropagateData &propdata)
static SYS_FORCE_INLINE bool isSameTime(fpreal a, fpreal b)
virtual void update(fpreal t)
Definition: DEP_MicroNode.h:87
void
Definition: png.h:1083
Global control whether dependencies can be cleared.
SYS_FORCE_INLINE bool isDirty() const
Flag accessors.
virtual bool requiresUpdate(fpreal t) const
Definition: DEP_MicroNode.h:94
DEP_API const DEP_ContextOptionDeps & DEPgetContextOptionDepsFromPtr(const DEP_ContextOptionDepsPtr &ptr)
SYS_FORCE_INLINE bool isTimeInterested() const
Flag accessors.
UT_ConcurrentSet< UT_StringHolder > DEP_ContextOptionDeps
UT_Array< DEP_MicroNode * > DEP_MicroNodeList
Definition: DEP_MicroNode.h:31
virtual bool isExporting() const
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
SYS_FORCE_INLINE const DEP_ContextOptionDeps & getContextOptionDeps() const
Flag accessors.
OIIO_FORCEINLINE vbool4 insert(const vbool4 &a, bool val)
Helper: substitute val for a[i].
Definition: simd.h:3436
UT_Function< bool(const DEP_MicroNode &, const DEP_MicroNode &) > TraverseVisitor
void setDirty(bool flag, bool allow_clear=true)
Flag accessors.
bool markVisitPass(int pass)
GLsizei GLenum * sources
Definition: glcorearb.h:2542
SYS_FORCE_INLINE void setIsOpDataMicroNode(bool b)
SYS_FORCE_INLINE int lastVisitPass() const
SYS_FORCE_INLINE void clearContextOptionDeps()
Flag accessors.
UT_Function< void(DEP_MicroNode &, DEP_MicroNode &) > Visitor
SYS_FORCE_INLINE int getNumExplicitInputs() const
Get the number of non-null inputs.
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
virtual bool isEvaluating() const
long long int64
Definition: SYS_Types.h:116
SYS_FORCE_INLINE bool isTimeDependent() const
Flag accessors.
SYS_FORCE_INLINE void addContextOptionDep(const UT_StringHolder &opt)
Flag accessors.
static SYS_FORCE_INLINE bool canClearDependencies()
Global control whether dependencies can be cleared.
Global control whether we can evaluate exports.
std::function< T > UT_Function
Definition: UT_Function.h:37
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLdouble t
Definition: glad.h:2397
SYS_FORCE_INLINE void addExplicitInput(DEP_MicroNode &inp)
Add an input that this micronode depends on.
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1069
static SYS_FORCE_INLINE bool canEvaluateExports()
Global control whether we can evaluate exports.
SYS_FORCE_INLINE bool hasContextOptionDeps() const
Flag accessors.
virtual void evaluateExports()
fpreal64 fpreal
Definition: SYS_Types.h:277
SYS_FORCE_INLINE void setTimeInterested(bool time_interested)
Flag accessors.
SYS_FORCE_INLINE bool isOpDataMicroNode() const
Flag accessors.
Propagation info for a dep micro node.
Definition: DEP_MicroNode.h:36
SYS_FORCE_INLINE void addContextOptionDeps(const DEP_ContextOptionDeps &opts)
Flag accessors.
DEP_API DEP_ContextOptionDeps & DEPcreateContextOptionDepsFromPtr(DEP_ContextOptionDepsPtr &ptr, DEP_ContextOptionDepsLock *lock=nullptr)
SYS_FORCE_INLINE int getNumExplicitOutputs() const
Get the number of non-null outputs.
bool isExprChange() const
Definition: DEP_MicroNode.h:46
#define DEP_API
Definition: DEP_API.h:10
GLint GLsizei count
Definition: glcorearb.h:405
SYS_FORCE_INLINE bool isstring() const
GLenum src
Definition: glcorearb.h:1793