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 
270  /// Global control whether dependencies can be cleared.
271  static SYS_FORCE_INLINE
273  { return (theKeepDependenciesCount == 0); }
274 
275  /// Global control whether we can evaluate exports
276  static SYS_FORCE_INLINE
278  { return (theBlockEvaluateExports == 0); }
279 
280  /// One true method to compare equality of time values for caching.
281  /// This particular form originates from what OP_Node::cook() did from the
282  /// dawn of time.
284  { return SYSequalZero(a - b); }
285 
286 protected:
287  /// These methods are overriden by subclasses to be used by the
288  /// dirty propagation algorithm.
289  /// @{
290 
291  /// Used to determine if a micronode is currently evaluating. If this
292  /// returns true, during dirty propagation, it will prevent dependencies
293  /// from being removed from it.
294  virtual bool isEvaluating() const
295  { return false; }
296 
297  /// evaluateExports() is called after isExporting() is noted to be true
298  /// during a dirty propagation pass initiated by dirtySubtree().
299  virtual void evaluateExports() { }
300 
301  /// Used to determine if a micronode requires its exports to be evaluated
302  /// during the propagation pass.
303  virtual bool isExporting() const
304  { return false; }
305 
306  /// @}
307 
309  void setIsOpDataMicroNode( bool b )
310  { myIsOPDataMicroNode = b; }
311 
312 private:
313  typedef UT_TBBSpinLock EdgeLock;
314  typedef UT_TBBSpinLock::Scope EdgeLockScope;
315 
316  typedef UT_Array<DEP_MicroNode *> MicroNodeInputPtrVector;
317  typedef UT_ConcurrentVector<DEP_MicroNode *> MicroNodeOutputPtrVector;
318  typedef UT_ArraySet<DEP_MicroNode*> MicroNodePtrSet;
319 
320  void clearExplicitInputs();
321  void clearExplicitOutputs();
322 
323  void compactExplicitInputsAndOutputs();
324 
325  static void compactVector(
326  MicroNodeOutputPtrVector &vec);
327  static void compactVector(
328  MicroNodeInputPtrVector &vec);
329 
330  template <typename MICRONODE_ARRAY>
331  static void getEdgeList(
332  const MICRONODE_ARRAY &edges,
333  DEP_MicroNodeList &micronodes);
334  template <typename MICRONODE_ARRAY>
335  static int countEdges(const MICRONODE_ARRAY &edges);
336 
337 private:
338 
339  /// The list of explicit edges for micronodes
340  // @{
341  EdgeLock myExplicitInputsLock;
342  MicroNodeInputPtrVector myExplicitInputs;
343  MicroNodePtrSet myExplicitInputsSet;
344  MicroNodeOutputPtrVector myExplicitOutputs;
345  // @}
346 
347  DEP_ContextOptionDepsLock myContextOptionDepsLock;
348  DEP_ContextOptionDepsPtr myContextOptionDeps;
349  int myLastVisitPass;
350 
351  bool myDirty:1;
352  bool myTimeDependent:1;
353  bool myTimeInterested:1;
354  bool myIsOPDataMicroNode:1;
355 
356  static int theKeepDependenciesCount;
357  static int theBlockEvaluateExports;
358 
359  friend class dep_Visitor;
362 };
363 
364 /// Global control whether dependencies can be cleared.
366 {
367 public:
369  { ++DEP_MicroNode::theKeepDependenciesCount; }
371  { --DEP_MicroNode::theKeepDependenciesCount; }
372 };
373 
374 /// Global control whether we can evaluate exports
376 {
377 public:
379  { ++DEP_MicroNode::theBlockEvaluateExports; }
381  { --DEP_MicroNode::theBlockEvaluateExports; }
382 };
383 
384 ///////////////////////////////////////////////////////////////////////////////
385 // Inline Implementations
386 //
387 
388 template <typename MICRONODE_ARRAY>
389 /* static */
390 int
391 DEP_MicroNode::countEdges(const MICRONODE_ARRAY &edges)
392 {
393  int count = 0;
394  for (DEP_MicroNode *e : edges)
395  {
396  if (e)
397  count++;
398  }
399  return count;
400 }
401 
402 #endif // __DEP_MICRONODE_H_INCLUDED__
vbool4 insert(const vbool4 &a, bool val)
Helper: substitute val for a[i].
Definition: simd.h:3414
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
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.
UT_UniquePtr< DEP_ContextOptionDeps > DEP_ContextOptionDepsPtr
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
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:88
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
SYS_FORCE_INLINE const DEP_ContextOptionDeps & getContextOptionDeps() const
Flag accessors.
GLenum src
Definition: glcorearb.h:1792
GLdouble GLdouble t
Definition: glew.h:1403
void setDirty(bool flag, bool allow_clear=true)
Flag accessors.
bool markVisitPass(int pass)
GLsizei GLenum * sources
Definition: glcorearb.h:2541
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.
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
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.
GLint GLsizei count
Definition: glcorearb.h:404
Global control whether we can evaluate exports.
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:844
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)
bool isExprChange() const
Definition: DEP_MicroNode.h:42
#define DEP_API
Definition: DEP_API.h:10
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