HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDGE_Dependency.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  * COMMENTS:
7  */
8 
9 #ifndef __PDGE_DEPENDENCY_H__
10 #define __PDGE_DEPENDENCY_H__
11 
12 #include "PDGE_API.h"
13 #include "PDGE_DebugUtils.h"
14 
15 #include <UT/UT_Array.h>
16 #include <UT/UT_ArraySet.h>
17 #include <UT/UT_NonCopyable.h>
18 #include <UT/UT_StringHolder.h>
19 #include <UT/UT_TBBSpinLock.h>
20 
21 #include <SYS/SYS_AtomicInt.h>
22 #include <SYS/SYS_Types.h>
23 
24 #include <utility>
25 
27 class PDGE_Evaluator;
28 class PDGE_Resolutions;
29 
30 /**
31  * Base class for dependencies types. Stores a Set of dependencies and a vector
32  * of dependents. Dependencies are added using the addDependency method, which
33  * ensures that no duplicate entries are added and adds back references on the
34  * dependent this object.
35  *
36  * A dependency relationship can optionally be marked as "partial" -- by
37  * default the partial flag is false. A partial dependency means that the
38  * dependent/child is interested in partial resolution updates from the
39  * dependency/parent it is attached to. When one of the parent's dependencies
40  * is resolved, it passes on that information to all dependents/children that
41  * are interested in partial updates.
42  *
43  * Once a dependency's resolution count reaches 0, it is marked as resolved
44  * and all dependents are inspected to see if they too have reached 0. A
45  * resolved dependency cannot be put back to the unresolved state unless it
46  * is reset. Resetting is not thread safe nor is it safe to do while a
47  * graph is being evalauated. It should only be done after an evaluation has
48  * completed.
49  *
50  * If PDGE_DEBUG_ENABLE_NAMES is defined, this class also stores a string
51  * name for the dependency for debug output.
52  */
54 {
55 public:
59 
61  using PartialPair = std::pair<PDGE_Dependency*, OwnerArray>;
63 
64  /// Dependency resolve state, passed back from the PDGE_DependencyOwner
65  /// when doing a full or partial resolve. The state has no impact on the
66  /// resolution of the dependency itself, but it propagate to dependents.
67  enum State : uint8
68  {
69  /// The dependency was successfully resolved
70  eSucceeded = 0x00,
71 
72  /// The dependency was resolved while evaluation was canceling
73  eCanceled = 0x01,
74 
75  /// The dependency encountered a failure during resolution
76  eFailed = 0x02,
77 
78  /// The dependency was reset during resolution and should not be
79  /// marked as resolved. This can only be used with leaf nodes in the
80  /// dependency graph.
81  eReset = 0x04,
82 
83  /// The state bits should be cleared before ORing the results from
84  /// dependency resolutions
85  eClear = 0x08,
86  };
87 
88 public:
89  /// Constructs a new dependency from a name and dependency owner. The
90  /// name is only stored if PDGE_DEBUG_ENABLE_NAMES is enabled.
91  PDGE_Dependency(const char* name,
92  PDGE_DependencyOwner* owner);
93 
94  /// Destroys this dependency object
95  virtual ~PDGE_Dependency();
96 
97  /// Returns the memory usage of this object
98  int64 getMemoryUsage(bool inclusive) const;
99 
100  /// Adds a dependency if it does not already exist. This method locks both
101  /// this object and the dependency. Returns true if the dependency was
102  /// added, else false.
103  bool addDependency(PDGE_Dependency* dependency,
104  bool partial = false,
105  PDGE_Dependency* propagate = nullptr,
106  bool is_any = false);
107 
108  /// Returns true if this object has any dependencies
109  inline bool hasDependencies() const
110  { return !myDependencies.empty(); }
111 
112  /// Returns true if this object has any dependents
113  inline bool hasDependents() const
114  { return !myDependents.isEmpty(); }
115 
116  /// Returns true if this object has the specifed dependency
117  inline bool hasDependency(PDGE_Dependency* dependency) const
118  {
119  if (!dependency)
120  return false;
121  return myDependencies.contains(dependency);
122  }
123 
124 
125  /// Returns true if this dependency is a partial source, i.e. it emits
126  /// partial resolve calls when one of its dependencies is resolved
127  inline bool isPartialSrc() const
128  { return myPartialSrc; }
129 
130  /// Returns true if this dependency is interested in receiving partial
131  /// resolve calls, when one of its dependencies is partially resolved.
132  inline bool isPartialDst() const
133  { return myPartialDst; }
134 
135  /// Returns true if this dependency has been resolved. Resolves dependencies
136  /// can only go back to being unresolved when calling reset().
137  inline bool isResolved() const
138  { return myIsResolved; }
139 
140  /// Returns true if this dependency has a heavy-weight evaluation routine
141  inline bool isHeavy() const
142  { return myIsHeavy; }
143 
144 
145  /// Returns the current state value of the dependency
146  inline uint8 state() const
147  { return myState; }
148 
149  /// Returns true if the current state value is set
150  inline bool hasState(State state) const
151  { return (myState & state); }
152 
153  /// ORs the state value into the current state
154  inline void updateState(State state)
155  { myState |= state; }
156 
157 
158  /// Returns the object that owns this dependency.
159  inline PDGE_DependencyOwner*
160  owner() const
161  { return myOwner; }
162 
163  /// Returns the set of all dependencies
164  inline const Set& dependencies() const
165  { return myDependencies; }
166 
167  /// Returns the array of all dependents
168  inline const Array& dependents() const
169  { return myDependents; }
170 
171  /// Returns the edge lock for this dependency object
172  inline UT_TBBSpinLock& edgeLock() const
173  { return myEdgeLock; }
174 
175 
176  /// Resets this dependecy object back to its default state. The initial
177  /// count determines the starting value of the unresolved counter.
178  void reset(int initial_count=0,
179  bool is_heavy=false);
180 
181  /// Unresolves a dependency and all of its dependents. This is different
182  /// than a reset because its non-destructive, and propgates state to
183  /// dependents. It is also threadsafe with other internal operations and
184  /// will interrupt and clear any resolutions that are already in progress.
185  /// It will not, however, be able to interrupt calls into the dependency
186  /// owner that may be changing state on that object.
187  void unresolve();
188 
189  /// Decrements the ref count on this dependency by one. Should be used
190  /// when this dependency is reset with a non-0 initial count, for adding
191  /// an N+1 dependency.
192  inline bool tryResolve(int count=1)
193  { return tryResolve(count, 0); }
194 
195  /// Increments the ref count on this dependency by one, for manual contorl
196  /// over the ref count
197  void increment(int count=1);
198 
199  /// Returns the debug full name, which includes the name of this object
200  /// and its owner. The as_dot argument indicates whether or not the name is
201  /// going to be used for dot graph output.
202  UT_StringHolder debugName(bool as_dot=false) const;
203 
204 private:
205  friend class PDGE_Resolutions;
206 
207  void unresolve(int unresolve_count, Set& visited);
208  void resolve(PDGE_Evaluator& evaluator,
209  PDGE_Resolutions& resolutions);
210  void partial(PDGE_Evaluator& evaluator,
211  PDGE_Resolutions& resolutions,
212  const OwnerArray& owner_array);
213  bool partialPairs(Partial& partial_pairs,
214  const OwnerArray& owner_array,
215  bool ascending) const;
216 
217 private:
218  inline bool tryResolve(int count, uint8 state)
219  {
220  if (state != 0)
221  {
222  UT_TBBSpinLock::Scope lock(myEdgeLock);
223  myState |= state;
224  }
225 
226  return (myUnresolvedCount.add(-count) == 0);
227  }
228 
229  inline void incrementInternal(int count)
230  { myUnresolvedCount.add(count); }
231 
232 private:
233  class EvaluationScope
234  {
235  public:
236  EvaluationScope(
237  PDGE_Dependency* dependency,
238  bool is_partial);
239  ~EvaluationScope();
240 
241  bool tryUnresolve(
242  PDGE_Resolutions& resolutions) const;
243 
244  private:
245  PDGE_Dependency* myDependency;
246  uint8 myUnresolveDepth;
247  bool myIsPartial;
248  };
249 
250 private:
251  Set myDependencies;
252  Array myDependents;
253 
254  PDGE_DependencyOwner* myOwner;
255  SYS_AtomicInt32 myUnresolvedCount;
256 
257  uint8 myState;
258  uint8 myUnresolveDepth;
259  uint8 myEvaluationDepth;
260 
261  mutable UT_TBBSpinLock myEdgeLock;
262 
263  bool myPartialSrc : 1;
264  bool myPartialDst : 1;
265  bool myIsResolved : 1;
266  bool myIsHeavy : 1;
267  bool myIsAny : 1;
268 
269 #ifdef PDGE_DEBUG_ENABLE_NAMES
270  UT_StringHolder myDebugName;
271 #endif
272 
273 #ifdef PDGE_DEBUG_ENABLE_IDS
274  int myId;
275 #endif
276 };
277 
278 #endif
bool tryResolve(int count=1)
Definition: ImfArray.h:47
uint8 state() const
Returns the current state value of the dependency.
UT_TBBSpinLock & edgeLock() const
Returns the edge lock for this dependency object.
One or more work items failed during the cook.
PDGE_DependencyOwner * owner() const
Returns the object that owns this dependency.
The service client is sent the "reset" command.
bool isHeavy() const
Returns true if this dependency has a heavy-weight evaluation routine.
bool isPartialDst() const
unsigned char uint8
Definition: SYS_Types.h:36
const Array & dependents() const
Returns the array of all dependents.
bool hasDependencies() const
Returns true if this object has any dependencies.
GLboolean reset
Definition: glad.h:5138
void updateState(State state)
ORs the state value into the current state.
long long int64
Definition: SYS_Types.h:116
GLuint const GLchar * name
Definition: glcorearb.h:786
std::pair< PDGE_Dependency *, OwnerArray > PartialPair
const Set & dependencies() const
Returns the set of all dependencies.
bool hasDependents() const
Returns true if this object has any dependents.
#define PDGE_API
Definition: PDGE_API.h:23
bool isPartialSrc() const
bool hasState(State state) const
Returns true if the current state value is set.
bool hasDependency(PDGE_Dependency *dependency) const
Returns true if this object has the specifed dependency.
One or more work items were canceled during the cook.
GLint GLsizei count
Definition: glcorearb.h:405
bool isResolved() const