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  uint8 prepareResolve(
209  PDGE_Evaluator& evaluator,
210  PDGE_Resolutions& resolutions);
211  void completeResolve(
212  PDGE_Resolutions& resolutions,
213  uint8 state);
214  void partial(
215  PDGE_Evaluator& evaluator,
216  PDGE_Resolutions& resolutions,
217  const OwnerArray& owner_array);
218  bool partialPairs(Partial& partial_pairs,
219  const OwnerArray& owner_array,
220  bool ascending,
221  bool combine) const;
222 
223 private:
224  inline bool tryResolve(int count, uint8 state)
225  {
226  if (state != 0)
227  {
228  UT_TBBSpinLock::Scope lock(myEdgeLock);
229  myState |= state;
230  }
231 
232  return (myUnresolvedCount.add(-count) == 0);
233  }
234 
235  inline void incrementInternal(int count)
236  { myUnresolvedCount.add(count); }
237 
238 private:
239  Set myDependencies;
240  Array myDependents;
241 
242  PDGE_DependencyOwner* myOwner;
243  SYS_AtomicInt32 myUnresolvedCount;
244 
245  uint8 myState;
246  uint8 myUnresolveDepth;
247  uint8 myCurrentDepth;
248  uint8 myEvaluationDepth;
249 
250  mutable UT_TBBSpinLock myEdgeLock;
251 
252  bool myPartialSrc : 1;
253  bool myPartialDst : 1;
254  bool myIsResolved : 1;
255  bool myIsHeavy : 1;
256  bool myIsAny : 1;
257 
258 #ifdef PDGE_DEBUG_ENABLE_NAMES
259  UT_StringHolder myDebugName;
260 #endif
261 
262 #ifdef PDGE_DEBUG_ENABLE_IDS
263  int myId;
264 #endif
265 };
266 
267 #endif
bool tryResolve(int count=1)
Definition: ImfArray.h:45
uint8 state() const
Returns the current state value of the dependency.
UT_TBBSpinLock & edgeLock() const
Returns the edge lock for this dependency object.
PDGE_DependencyOwner * owner() const
Returns the object that owns this dependency.
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
The service client is sent the "reset" command.
bool isPartialSrc() const
bool hasState(State state) const
Returns true if the current state value is set.
One or more work items were canceled during the cook.
One or more work items failed during the cook.
bool hasDependency(PDGE_Dependency *dependency) const
Returns true if this object has the specifed dependency.
GLint GLsizei count
Definition: glcorearb.h:405
bool isResolved() const