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