HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDG_GraphContext.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 __PDG_GRAPH_CONTEXT_H__
10 #define __PDG_GRAPH_CONTEXT_H__
11 
12 #include "PDG_API.h"
13 
14 #include "PDG_ApplicationShim.h"
15 #include "PDG_CheckpointManager.h"
16 #include "PDG_CommandManager.h"
17 #include "PDG_CookState.h"
18 #include "PDG_EventEmitter.h"
19 #include "PDG_EventQueue.h"
20 #include "PDG_Graph.h"
21 #include "PDG_Types.h"
22 
24 
25 #include <PDGE/PDGE_Evaluator.h>
26 #include <PDGT/PDGT_ValueArgs.h>
27 
28 #include <UT/UT_Lock.h>
29 #include <UT/UT_Map.h>
30 #include <UT/UT_NonCopyable.h>
31 #include <UT/UT_Set.h>
32 #include <UT/UT_StringArray.h>
33 #include <UT/UT_StringHolder.h>
34 #include <UT/UT_StringMap.h>
35 #include <UT/UT_TBBSpinLock.h>
36 #include <UT/UT_UniquePtr.h>
37 #include <UT/UT_ValArray.h>
38 #include <UT/UT_VectorTypes.h>
39 
40 #include <SYS/SYS_AtomicInt.h>
41 
42 class PDG_CommandChunk;
43 class PDG_Command;
44 struct PDG_CookOptions;
45 class PDG_InProcessScheduler;
46 struct PDG_MemoryInfo;
47 class PDG_Scheduler;
48 class PDG_SchedulerType;
49 class PDG_ServiceScheduler;
50 class PDG_WorkItem;
51 
52 class UT_Thread;
53 class UT_WorkBuffer;
54 
55 /*
56  * Stores core components of a PDG graph, such as the node graph itself, the
57  * schedulers and the event queue
58  */
60 {
61 public:
63 
64  /*
65  * Observer that gets called each time a graph context is created or
66  * destroyed
67  */
69  {
70  public:
71  Observer() {}
72  virtual ~Observer() {}
74 
75  virtual void onPDGGraphContextRegistered(
76  PDG_GraphContext *context) = 0;
77  virtual void onPDGGraphContextDeregistered(
78  PDG_GraphContext *context) = 0;
79  };
80 
81 public:
82  /// Returns the context with the specified name, or nullptr if no such
83  /// context exists
84  static PDG_GraphContext* contextByName(const UT_StringHolder& name);
85 
86  /// Returns the context with the specified ID, or nullptr if no such
87  /// context exists
88  static PDG_GraphContext* contextByID(int id);
89 
90  /// Returns the list of all registered context names
91  static UT_StringArray contextNames();
92 
93  /// Returns the list of all registered context IDs
94  static UT_IntArray contextIDs();
95 
96  /// Adds and removes a global observer, which is notified each time a
97  /// graph context is created
98  static void addGraphContextObserver(Observer *observer);
99  static void removeGraphContextObserver(Observer *observer);
100 
101  /// Constructs a new context with the specified name and id. It is up to
102  /// the caller to supply a unique id, which is typically set to an
103  /// application-specific value such as the unique ID of a TOP_Network.
105  const char* name="context",
106  int id=-1);
107  ~PDG_GraphContext() override;
108 
109  /// Returns the list of supported event types
110  PDG_EventEmitter::Filter& supportedEventTypes() const override;
111 
112  /// Returns total memory usage of the graph and schedulers contained in
113  /// this context
114  int64 getMemoryUsage(
115  bool inclusive) const override;
116 
117  /// Returns a fined grained breakdown of memory used by the nodes and
118  /// work items in the graph context
119  void memoryInfo(
120  PDG_MemoryInfo& memory_info,
121  bool inclusive) const;
122 
123  /// Sets the application-specific graph object
124  void setAppGraph(PDG_ApplicationShim::Graph* graph)
125  { myAppGraph = graph; }
126 
127  /// The graph owned by this instance
129  { return &myGraph; }
130 
131  /// Returns the event queue associted with this context
133  { return myEventQueue.get(); }
134 
135  /// Returns the checkpoint manager associated with this instance
137  { return &myCheckpointManager; }
138 
139  /// The unique name of the graph context
140  const UT_StringHolder& name() const
141  { return myName; }
142 
143  /// Returns the id of the graph context
144  int id() const
145  { return myId; }
146 
147  /// Returns the default work item label
148  bool defaultWorkItemLabel(
149  UT_StringHolder& label) const;
150 
151  /// Returns the current cook state object, which stores various
152  /// metadata relating to the active grap hook
153  const PDG_CookState& cookState() const
154  { return myCookState; }
155 
156  /// Returns true if the context is actively cooking
157  bool cooking() const
158  { return myCooking; }
159 
160  /// Returns true if the context is processing a cancel request from the
161  /// user
162  bool canceling() const
163  { return myCanceling; }
164 
165 
166  /// Returns the current default scheduler, or nullptr if no schedulers
167  /// exist. The first scheduled created is automatically set as the
168  /// default.
170  { return myDefaultScheduler; }
171 
172  /// Returns the service scheduler, which is used to process work items
173  /// from nodes with service mode enabled.
174  PDG_ServiceScheduler* serviceScheduler() const
175  { return myServiceScheduler; }
176 
177  /// Returns the default in process scheduler, which is used to process
178  /// in process items that need to run on the main thread
179  PDG_InProcessScheduler* inProcessScheduler() const
180  { return myInProcessScheduler; }
181 
182  /// Adds a new scheduler instance to the graph context
183  void addScheduler(
184  const UT_StringHolder& name,
185  PDG_SchedulerPtr scheduler);
186 
187  /// Adds a new scheduler constructed from the specified type instance,
188  /// and with the desired named. This method ensures that the name is
189  /// unique.
190  PDG_Scheduler* addScheduler(
191  const UT_StringHolder& preferred_name,
192  PDG_SchedulerType* scheduler_type,
193  UT_WorkBuffer& errors);
194 
195  /// Removes the scheduler with the specified name, and returns true if
196  /// it was found/removed.
197  bool removeScheduler(
198  const UT_StringHolder& name);
199 
200  /// Sets the specified scheduler as the new default.
201  void setDefaultScheduler(
202  PDG_Scheduler* scheduler);
203 
204  /// Returns the scheduler with the specified name, or nullptr if no such
205  /// scheduler exists.
206  PDG_Scheduler* schedulerForName(
207  const UT_StringHolder& name) const;
208 
209  /// Returns the map of scheduler name -> scheduler pointer that exist
210  /// in the graph context
211  const SchedulerMap& schedulers() const;
212 
213  /// Returns shared server info by searching for it across all active
214  /// schedulers
215  PDGT_ValueArgs getSharedServerInfo(
216  const UT_StringHolder &sharedserver_name);
217 
218  /// Cleans the temporary file directory for the specified scheduler
219  void cleanTempDirectory(
220  const UT_StringHolder& scheduler_name);
221 
222  /// Cancel the cook if it's running and block until it's finished canceling
223  void cancelCook();
224 
225  /// Similar to cancel, except work items that are in-progress are not
226  /// killed, and results can be collected later.
227  void pauseCook();
228 
229  /// Cooks the graph with the specified options. Returns false if there was
230  /// a probably starting the cook
231  bool cook(
232  const PDG_CookOptions& options,
233  UT_WorkBuffer& errors);
234 
235 
236  /// Returns the current open command chunk
237  PDG_CommandChunk* currentChunk() const;
238 
239  /// Opens a new command chunk with an option description string
240  PDG_CommandChunk* openChunk(UT_StringHolder description = "");
241 
242  /// Opens a new delayed command chunk
243  PDG_CommandChunk* openChunk(
244  bool delayed,
245  const UT_StringHolder& description);
246 
247  /// Record, undo and redo commands
248  bool commitChunk(UT_WorkBuffer& errors);
249  bool rollbackChunk(UT_WorkBuffer& errors);
250  bool undoIt(UT_WorkBuffer& errors);
251  bool redoIt(UT_WorkBuffer& errors);
252  bool recordCommand(
254  UT_WorkBuffer& errors);
255 
256  /// Returns the number of entries in the command manager
257  int stateCount() const;
258 
259  /// Returns the number of entries in the current command chunk
260  int chunkDepth() const;
261 
262  /// Dumps the current command manager contents to the input buffer
263  void commandDescriptions(
264  UT_WorkBuffer& buffer) const;
265 
266  /// Serializes the node graph to a buffer
267  void serializeGraph(UT_WorkBuffer& buffer);
268  void serializeGraph(
269  const UT_StringHolder& file_name,
270  UT_StringHolder extras = "");
271 
272  /// Serializes the work item graph to a buffer
273  void serializeWorkItems(UT_WorkBuffer& buffer);
274  void serializeWorkItems(
275  const UT_StringHolder& file_name,
276  UT_StringHolder extras = "");
277 
278  /// Serializes both the work item and node graph
279  void serialize(UT_WorkBuffer& buffer);
280  void serialize(
281  const UT_StringHolder& file_name,
282  UT_StringHolder extras = "");
283 
284  /// Serializes the specified work item to JSON
285  UT_StringHolder serializeWorkItemToJSON(
286  PDG_WorkItem* work_item,
287  bool pretty_print) const;
288 
289  /// Loads a work item from JSON
290  PDG_WorkItem* deserializeWorkItemFromJSON(
291  const UT_StringHolder& buffer,
292  UT_WorkBuffer& errors);
293 
294  /// Loads a work item checkpoint file
295  bool deserializeCheckpoint(
296  const UT_StringHolder& file_path,
297  UT_WorkBuffer& errors);
298 
299  /// Begins deserializing a work item graph, part of the Python
300  /// serialization API
301  void beginDeserialization();
302 
303  /// Deserializes a work item from a serialization struct
304  void addWorkItem(
305  const PDG_WorkItemSerialization& serialization);
306 
307  /// Adds a dependency between two work items, given their names
308  void addWorkItemDependency(
309  const UT_StringHolder& item_name,
310  const UT_StringHolder& dep_name,
311  bool required,
312  bool user_defined);
313 
314  /// Adds a dependency between two work items, given their IDs
315  void addWorkItemDependencyId(
316  PDG_WorkItemID item_id,
317  PDG_WorkItemID dep_id,
318  bool required,
319  bool user_defined);
320 
321  /// Adds a propagate dependency between two work iems, given their names
323  const UT_StringHolder& item_name,
324  const UT_StringHolder& dep_name) {}
325 
326  /// Adds a propagate dependency between two work iems, given their IDs
328  PDG_WorkItemID item_id,
329  PDG_WorkItemID dep_id) {}
330 
331  /// Adds work item output files onto the specified work item, by name
332  void addWorkItemResults(
333  const UT_StringHolder& item_name,
334  const UT_StringArray& results,
335  const UT_StringArray& tags,
336  const UT_Array<int64>& hash_codes,
337  const UT_Array<bool>& is_expected,
338  const UT_Array<bool>& is_owned);
339 
340  /// Adds work item output files onto the specified work item, by id
341  void addWorkItemResultsId(
342  PDG_WorkItemID item_id,
343  const UT_StringArray& results,
344  const UT_StringArray& tags,
345  const UT_Array<int64>& hash_codes,
346  const UT_Array<bool>& is_expected,
347  const UT_Array<bool>& is_owned);
348 
349  /// Commits a partially deserialized work item to the PDG graph
350  void commitWorkItem(
351  const UT_StringHolder& item_name);
352  void commitWorkItemId(PDG_WorkItemID item_id);
353 
354  /// Runs a function with the context lock held, for a specific graph
355  /// context. If a context with the name does not exist, the function is
356  /// not called.
357  template <typename Func>
359  const UT_StringHolder& name,
360  const Func& func)
361  {
362  UT_Lock::Scope auto_lock(
363  theContextLock);
364  auto it = theContextMap.find(name);
365  if (it != theContextMap.end())
366  func(it->second);
367  }
368 
369  /// Runs a function over all graph contexts with the context lock held
370  template <typename Func>
371  static void safeGraphContextAccess(const Func& func)
372  {
373  UT_Lock::Scope auto_lock(
374  theContextLock);
375  for (auto&& entry : theContextMap)
376  func(entry.second);
377  }
378 
379  /// Runs a function with the scheduler lock held
380  template<typename Func>
382  const UT_StringHolder& name,
383  const Func& func)
384  {
385  UT_Lock::Scope schedulersLock(
386  mySchedulersLock);
387 
388  auto it = mySchedulers.find(name);
389  if (it != mySchedulers.end())
390  func(it->second.get());
391  }
392 
393 protected:
394  bool preEvaluation() override;
395  bool tickEvaluation() override;
396  void postEvaluation(
397  PDGE_Evaluator::State state,
398  bool canceled) override;
399 
400 private:
401  static void registerContext(PDG_GraphContext* context);
402  static void deregisterContext(PDG_GraphContext* context);
403  static void onExit(void* data);
404  static void onPyExit();
405  static void* doTickThread(void* data);
406 
407  void commitWorkItemInternal(
408  PDG_WorkItem* work_item);
409  void addWorkItemDependencyInternal(
410  PDG_WorkItem* work_item,
411  PDG_WorkItem* dependency,
412  bool required,
413  bool user_defined);
414  void addWorkItemResultsInternal(
415  PDG_WorkItem* work_item,
416  const UT_StringArray& results,
417  const UT_StringArray& tags,
418  const UT_Array<int64>& hash_codes,
419  const UT_Array<bool>& is_expected,
420  const UT_Array<bool>& is_owned);
421 
422  void serializeWorkItem(
424  PDG_WorkItemIDMap& serialization_map,
425  const PDG_WorkItem* item) const;
426  void serializeWorkItemCommit(
428  PDG_WorkItemIDMap& serialization_map,
429  const PDG_WorkItem* item) const;
430 
431  PDG_GraphContext* context()
432  { return this; }
433 
434 private:
435  using ContextMap = UT_StringMap<PDG_GraphContext*>;
436  using ObserverSet = UT_Set<Observer*>;
437 
438  static ContextMap theContextMap;
439  static UT_Lock theContextLock;
440  static ObserverSet theObservers;
441  static UT_TBBSpinLock theObserverLock;
442  static bool theRegisteredAtExit;
443 
444  UT_StringHolder myName;
445  int myId;
446 
447  PDG_Graph myGraph;
448  PDG_CommandManager myUserCmdManager;
449  PDG_WorkItemSerialization::Map mySerializationMap;
450 
451  PDG_CheckpointManager myCheckpointManager;
452 
453  mutable UT_Lock mySchedulersLock;
454  SchedulerMap mySchedulers;
455 
456  PDG_Scheduler* myDefaultScheduler;
457  PDG_ServiceScheduler* myServiceScheduler;
458  PDG_InProcessScheduler* myInProcessScheduler;
459 
460  UT_Thread* myTickThread;
461  PDG_ApplicationShim::Graph* myAppGraph;
462 
463  PDG_CookState myCookState;
464 
465  bool myCooking;
466  bool myCanceling;
467  SYS_AtomicInt32 myTickActive;
468 
469  UT_UniquePtr<PDG_EventQueue> myEventQueue;
470 };
471 
472 #endif /* __PDG_GRAPH_CONTEXT_H__ */
State
The state of the evaluator object.
PDG_ServiceScheduler * serviceScheduler() const
Definition: UT_Set.h:58
PDG_CheckpointManager * checkpointManager()
Returns the checkpoint manager associated with this instance.
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2545
UT_SharedPtr< PDG_Scheduler > PDG_SchedulerPtr
Definition: PDG_Types.h:43
#define PDG_API
Definition: PDG_API.h:23
PDG_InProcessScheduler * inProcessScheduler() const
static void safeGraphContextAccess(const UT_StringHolder &name, const Func &func)
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
bool canceling() const
int id() const
Returns the id of the graph context.
void addWorkItemPropagateDep(const UT_StringHolder &item_name, const UT_StringHolder &dep_name)
Adds a propagate dependency between two work iems, given their names.
Definition: core.h:760
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
void addWorkItemPropagateDepId(PDG_WorkItemID item_id, PDG_WorkItemID dep_id)
Adds a propagate dependency between two work iems, given their IDs.
long long int64
Definition: SYS_Types.h:116
static void safeGraphContextAccess(const Func &func)
Runs a function over all graph contexts with the context lock held.
bool cooking() const
Returns true if the context is actively cooking.
void safeSchedulerAccess(const UT_StringHolder &name, const Func &func)
Runs a function with the scheduler lock held.
GLuint const GLchar * name
Definition: glcorearb.h:786
PDG_EventQueue * getEventQueue()
Returns the event queue associted with this context.
const PDG_CookState & cookState() const
PDG_Graph * graph()
The graph owned by this instance.
GLenum func
Definition: glcorearb.h:783
exint PDG_WorkItemID
Type defs for unique work item IDs.
Definition: PDG_Types.h:48
#define const
Definition: zconf.h:214
PDG_Scheduler * defaultScheduler() const
Definition: format.h:895
const UT_StringHolder & name() const
The unique name of the graph context.