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 the number of non-null outputs
122  { return countEdges(myExplicitOutputs); }
123 
124  // @}
125 
126  typedef hboost::function2<
127  void,
128  DEP_MicroNode & /*micronode*/,
129  DEP_MicroNode & /*src*/
131  typedef hboost::function2<
132  bool,
133  const DEP_MicroNode & /*micronode*/,
134  const DEP_MicroNode & /*src*/
136 
137  /// Mark this micronode and all its dependents as dirty. The global dirty
138  /// counter will be incremented once for each call to propagateDirty().
139  ///
140  /// @param client_visit Called for each micronode that is dirtied
141  /// @param only_outputs If true, then *this is ommitted from being
142  /// dirtied
143  ///
144  /// @note This method is NOT thread-safe with *any* operation on *any*
145  /// micronode. Only call this when no other micronode operations are
146  /// running.
147  void propagateDirty(
148  Visitor client_visit,
149  bool only_outputs = false);
150 
151  /// Callbacks for what to do when the micronode becomes dirty.
152  /// Derived micronodes can override this. Note that it requires
153  /// knowledge of who made it dirty as they may behave differently.
154  /// Currently used by OP_Node::propagateDirtyMicroNode
155  virtual void becameDirty(DEP_MicroNode &src, 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 
173  int lastVisitPass() const
174  { return myLastVisitPass; }
175 
176  /// Obtain approximate memory usage
177  virtual int64 getMemoryUsage(bool inclusive) const;
178 
179  /// Dump contents to output stream, strictly for debugging purposes
180  virtual void dump(
181  std::ostream &os,
182  const char *prefix = 0,
183  int indent_level = 0) const;
184  /// Dump the contents is a manner more suitable for DOT.
185  void dumpAsDOT(
186  std::ostream &os,
187  const char *prefix = 0,
188  int indent_level = 0) const;
189 
190  typedef bool (DEP_MicroNode::*GetFlag)() const;
191  typedef void (DEP_MicroNode::*SetFlag)(bool flag);
192 
193  /// Set time dependent flag if any explicit inputs are set.
194  /// Returns true if any explicit inputs are true.
195  bool inheritTimeDependentFromExplicitInputs();
196 
197  /// Set time interested flag if any explicit inputs are set.
198  /// Returns true if any explicit inputs are true.
199  bool inheritTimeInterestedFromExplicitInputs();
200 
201  /// Flag accessors
202  // @{
203  bool isDirty() const
204  { return myDirty; }
205  void setDirty(bool flag, bool allow_clear=true)
206  {
207  myDirty = flag;
208  if (allow_clear
209  && myDirty
210  && canClearDependencies())
211  {
212  clearInputs();
213  }
214  }
215 
216  bool isTimeDependent() const
217  { return myTimeDependent; }
218  void setTimeDependent(bool time_dependent)
219  { myTimeDependent = time_dependent; }
220 
221  bool isTimeInterested() const
222  { return myTimeInterested; }
223  void setTimeInterested(bool time_interested)
224  { myTimeInterested = time_interested; }
225 
226  bool isOpDataMicroNode() const
227  { return myIsOPDataMicroNode; }
228  // @}
229 
230  /// Global control whether dependencies can be cleared.
231  static bool canClearDependencies()
232  { return (theKeepDependenciesCount == 0); }
233 
234  /// Global control whether we can evaluate exports
235  static bool canEvaluateExports()
236  { return (theBlockEvaluateExports == 0); }
237 
238  /// One true method to compare equality of time values for caching.
239  /// This particular form originates from what OP_Node::cook() did from the
240  /// dawn of time.
242  { return SYSequalZero(a - b); }
243 
244 
245 protected:
246 
247  /// These methods are overriden by subclasses to be used by the
248  /// dirty propagation algorithm.
249  /// @{
250 
251  /// Used to determine if a micronode is currently evaluating. If this
252  /// returns true, during dirty propagation, it will prevent dependencies
253  /// from being removed from it.
254  virtual bool isEvaluating() const
255  { return false; }
256 
257  /// evaluateExports() is called after isExporting() is noted to be true
258  /// during a dirty propagation pass initiated by dirtySubtree().
259  virtual void evaluateExports() { }
260 
261  /// Used to determine if a micronode requires its exports to be evaluated
262  /// during the propagation pass.
263  virtual bool isExporting() const
264  { return false; }
265 
266  /// @}
267 
268  void setIsOpDataMicroNode( bool b )
269  { myIsOPDataMicroNode = b; }
270 
271 private:
272 
273  typedef UT_TBBSpinLock EdgeLock;
274  typedef UT_TBBSpinLock::Scope EdgeLockScope;
275 
276  typedef UT_ConcurrentVector<DEP_MicroNode *>
277  MicroNodePtrVector;
278  typedef hboost::function1<MicroNodePtrVector &, DEP_MicroNode &>
279  AdjacentFunc;
280 
281  void clearExplicitInputs();
282  void clearExplicitOutputs();
283 
284  void compactExplicitInputsAndOutputs();
285 
286  template <GetFlag GET_FLAG, SetFlag SET_FLAG>
287  bool inheritFlag(const MicroNodePtrVector &inputs);
288 
289  static MicroNodePtrVector & getRawExplicitInputs(DEP_MicroNode &n)
290  { return n.myExplicitInputs; }
291  static MicroNodePtrVector & getRawExplicitOutputs(DEP_MicroNode &n)
292  { return n.myExplicitOutputs; }
293 
294  static void clearEdges(
295  DEP_MicroNode *self,
296  MicroNodePtrVector &vec,
297  AdjacentFunc get_adjacent);
298 
299  static void compactVector(
300  MicroNodePtrVector &vec);
301 
302  static void getEdgeList(
303  const MicroNodePtrVector &edges,
304  DEP_MicroNodeList &micronodes);
305  static int countEdges(const MicroNodePtrVector &edges);
306 
307 private:
308 
309  /// The list of explicit edges for micronodes
310  // @{
311  EdgeLock myExplicitInputsLock;
312  MicroNodePtrVector myExplicitInputs;
313  MicroNodePtrVector myExplicitOutputs;
314  // @}
315 
316  int myLastVisitPass;
317 
318  bool myDirty:1;
319  bool myTimeDependent:1;
320  bool myTimeInterested:1;
321  bool myIsOPDataMicroNode:1;
322 
323  static int theKeepDependenciesCount;
324  static int theBlockEvaluateExports;
325 
326  friend class dep_Visitor;
329 
330 };
331 
332 
333 /// Global control whether dependencies can be cleared.
335 {
336 public:
338  { ++DEP_MicroNode::theKeepDependenciesCount; }
340  { --DEP_MicroNode::theKeepDependenciesCount; }
341 };
342 
343 
344 /// Global control whether we can evaluate exports
346 {
347 public:
349  { ++DEP_MicroNode::theBlockEvaluateExports; }
351  { --DEP_MicroNode::theBlockEvaluateExports; }
352 };
353 
354 
355 #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:100
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:263
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