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