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