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