HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PDG_EvaluationContext.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_EVALUATION_CONTEXT_H__
10 #define __PDG_EVALUATION_CONTEXT_H__
11 
12 #include "PDG_API.h"
13 
14 #include "PDG_AttributeEvaluator.h"
15 #include "PDG_AttributeInfo.h"
16 
17 #include <PY/PY_Result.h>
18 
19 #include <UT/UT_ErrorManager.h>
20 #include <UT/UT_Function.h>
21 #include <UT/UT_NonCopyable.h>
22 #include <UT/UT_StringArray.h>
23 #include <UT/UT_StringMap.h>
24 
25 #include <SYS/SYS_Hash.h>
26 
27 #include <iosfwd>
28 
29 class PY_PyObject;
30 class PY_CompiledCode;
32 
34 class PDG_Graph;
35 class PDG_GraphContext;
36 class PDG_Node;
37 class PDG_WorkItem;
38 
39 class UT_IStream;
40 class UT_StringHolder;
41 class UT_WorkBuffer;
42 
43 /*
44  * A context for evaluation PDG Python expression. Each thread-local context has
45  * its own local dictionary which it uses to evaluate expressions, allowing
46  * node authors to insert their own local variables in node callbacks. The dict
47  * is cleared at the beginning of each callback invocation.
48  */
50 {
51 public:
52  /// Evaluation context state
53  enum State
54  {
59  eStateDirtying
60  };
61 
62  /// Enumeration of python script evaluation results
64  {
65  /// The script succeeded without any exceptions
67 
68  /// The script encountered an error or exception
70 
71  /// The script was aborted, e.g. with a sys.exit(..) call
72  eResultAbort
73  };
74 
75  /// Scoped reset of the thread-local context cooking/generation state
77  {
78  public:
79  StateScope(
80  int thread,
81  State state,
82  bool localize,
83  const PDG_Node* node,
84  const PDG_WorkItem* work_item,
85  PDG_GraphContext* context);
86  StateScope(
87  int thread,
88  State state,
89  bool localize,
90  const PDG_Node* node,
91  const PDG_WorkItem* work_item,
92  fpreal time);
93  ~StateScope();
95 
96  private:
97  void init(
98  int thread,
99  State state,
100  bool localize,
101  const PDG_Node* node,
102  const PDG_WorkItem* work_item,
103  fpreal time);
104 
105  private:
106  UT_AutoErrorManager myErrorManager;
107  const PDG_Node* myActiveNode;
108  const PDG_Node* myNode;
109  const PDG_WorkItem* myPreviousItem;
110  PY_PyObject* myLocals;
111  fpreal myEvalTime;
112  int myThread;
113 
114  State myState;
115  bool myParameterError;
116  bool myPushedDir;
117  bool myLocalize;
118  bool myPreviousParent;
119  };
120 
121  /// Scoped setter of local work item
123  {
124  public:
125  ItemScope(int thread,
126  const PDG_WorkItem* work_item,
127  bool is_parent);
128  ~ItemScope();
130 
131  private:
132  const PDG_WorkItem* myPreviousItem;
133  int myThread;
134  bool myPreviousParent;
135  };
136 
137  /// Scoped block that records PDG attribute evaluations
139  {
140  public:
142 
143  public:
147 
148  void reset();
149  void record(const UT_StringHolder& attrib);
150  const UT_StringArray& expressionAttribs() const
151  { return myExpressionAttribs; }
152 
153  private:
154  UT_StringArray myExpressionAttribs;
155  AttribRecordScope* myPreviousRecord;
156  int myThread;
157  };
158 
159  /// Utility function type for converting a PDG_WorkItem* to a PY_PyObject.
161 
162 public:
163  /// Constructs a new context. Should not be called, only here because the
164  /// thread local var needs it to be public instead of private.
167 
169 
170  /// Returns the built-in functions that are available in the the context
171  static void builtinFunctions(UT_StringArray& functions);
172 
173  /// Sets the work item caster function, which is used when setting a work
174  /// item as a Python dictonary variable from C++. If the caster function
175  /// is not installed, a slower code path that looks up the work item from
176  /// the graph is used instead.
177  static void setWorkItemCaster(
178  const WorkItemCaster& caster);
179 
180 
181  /// Configures whether or not all PDG_EvaluationContext instance should
182  /// use Python.
183  static void setUsePython(bool use_python);
184 
185  /// Returns the shared Python context in which expressions evaluated
186  static PY_EvaluationContext& getExpressionContext();
187 
188  /// Returns the thread-local PDG_EvaluationContext instance
189  static PDG_EvaluationContext* getContext();
190 
191  /// Returns the thread-local PDG_EvaluationContext instance for the
192  /// specific thread
193  static PDG_EvaluationContext* getContext(int thread);
194 
195 
196  /// Sets the global batch subitem index. Used when constructing an active
197  /// work item on the job side, to make attributes available.
198  static void setGlobalSubItemIndex(int index,
199  bool dirty);
200 
201  /// Sets the global active work item. Used for setting an active item
202  /// in the current houdini session for debugging, or as part of a houdini-
203  /// based job on the farm.
204  static void setGlobalWorkItem(
205  const PDG_WorkItem* work_item,
206  bool dirty);
207 
208  /// Sets the global active item for an out of process work item job
209  static void setGlobalJobWorkItem(
210  PDG_WorkItem* work_item,
211  const UT_StringHolder& node_name,
212  const UT_StringHolder& scheduler_name);
213 
214  /// Adds the specified attributes to the global set of time dependent
215  /// attribs, for out-of-process batch cooks that have different attribute
216  /// values at each frame.
217  static void setTimeDependentAttribs(
218  const UT_ArrayStringSet& names,
219  bool dirty);
220 
221  /// Dirties all dependent attributes
222  static void dirtyAllAttribs();
223 
224  /// Saves all attributes and field from the global active work item to the
225  /// specified output stream.
226  static bool saveGlobalWorkItem(std::ostream &os);
227 
228  /// Loads the data from the specified input stream into a free-standing
229  /// work item, which is saved as the default global item until one is
230  /// selected in the UI.
231  static bool loadGlobalWorkItem(UT_IStream& is);
232 
233  /// Quries the global work item. This should not be used in most cases,
234  /// except for when checking if the global item needs to be cleared
235  static const PDG_WorkItem* globalWorkItem(bool sub_item);
236 
237  /// Queries the global node name. Used on the job side to determine the
238  /// work item name, since the work item does not directly store a string
239  /// name on its own.
240  static const UT_StringHolder& globalNodeName();
241 
242  /// Queries the global scheduler name. Used on the job side to determine
243  /// the submitting scheduler name, since the work item doesn't have direct
244  /// access to the scheduler itself.
245  static const UT_StringHolder& globalSchedulerName();
246 
247  /// Returns true if PDG attribute evaluation is time dependent, else false
248  static bool useTimeDependentAttribs();
249 
250  /// Returns true if the specified attribute is time dependent, else false
251  static bool isTimeDependent(
252  const UT_StringHolder& name);
253 
254  /// Queries the current active work item. If a PDG cook is in-progress, this
255  /// will return the thread-local item. If there is no active cook, this will
256  /// return whatever global work item was set
257  static const PDG_WorkItem* activeWorkItem(int thread);
258 
259  /// Queries the thread local is-parent flag
260  static bool activeIsParent(int thread);
261 
262  /// Returns true if the thread local state is generating
263  static bool isLocalGenerating(int thread);
264 
265  /// Returns true if the thread local state is runtime
266  static bool isLocalRuntime(int thread);
267 
268  /// Returns true if the thread local state indicates the thread is being
269  /// used to do PDG work
270  static bool isLocalActive(int thread);
271 
272  /// Returns true if a PDG job is active, either in process or out of
273  /// process, for the specified thread. Out of process jobs that load in a
274  /// PDG work item are always considered to be active PDG jobs. Otherwise,
275  /// this method falls back to ::isLocalActive.
276  static bool isLocalCookingPDG(int thread);
277 
278  /// Returns the current state of the thread local evaluation context
279  static State localState(int thread);
280 
281  /// Returns the current evaluation time of the thread local context
282  static fpreal localEvalTime(int thread);
283 
284  /// Returns the thread-local active node
285  static const PDG_Node* localActiveNode(int thread);
286 
287 
288  /// Gets an attribute evaluator
289  static PDG_AttributeEvaluator* createAttributeEvaluator(int thread,
290  const char* name);
291 
292  /// Sets the Python evaluation dictionary directly
293  static void setDict(int thread, PY_PyObject* locals);
294 
295  /// Returns the local Python dictionary object
296  static PY_PyObject* localDict(int thread);
297 
298  /// Sets or updates primitive values in the Python dictionary
299  static void updateDict(int thread,
300  const UT_StringHolder& name,
301  fpreal value);
302  static void updateDict(int thread,
303  const UT_StringHolder& name,
304  int value);
305  static void updateDict(int thread,
306  const UT_StringHolder& name,
307  const UT_StringHolder& value);
308 
309  /// Sets or updates a PDG work in the Python dictionary
310  static void updateDict(int thread,
311  const UT_StringHolder& name,
312  const PDG_WorkItem* work_item);
313 
314  /// Sets or updates a PDG node in the Python dictionary
315  static void updateDict(int thread,
316  const UT_StringHolder& name,
317  const PDG_Node* node);
318 
319  /// Sets or update a PDG graph inthe Python dictionary
320  static void updateDict(int thread,
321  const UT_StringHolder& name,
322  const PDG_Graph* graph);
323 
324  /// Resets the thread-local context's local Python dictionary
325  static void resetDict(int thread);
326 
327 
328  /// Primitive Python eval methods (loat, int, string)
329  static EvaluationResult evaluate(int thread,
330  const PY_CompiledCode& expression,
331  fpreal& result,
332  UT_WorkBuffer& errors);
333  static EvaluationResult evaluate(int thread,
334  const PY_CompiledCode& expression,
335  exint& result,
336  UT_WorkBuffer& errors);
337  static EvaluationResult evaluate(int thread,
338  const PY_CompiledCode& expression,
339  UT_StringHolder& result,
340  UT_WorkBuffer& errors);
341 
342  /// PyObject eval method
343  static EvaluationResult evaluate(int thread,
344  const PY_CompiledCode& expression,
345  void*& result,
346  UT_WorkBuffer& errors);
347 
348  /// Void/no-result eval method
349  static EvaluationResult evaluate(int thread,
350  const PY_CompiledCode& expression,
351  UT_WorkBuffer& errors);
352 
353  /// Evaluates an abritrary string and returns the PyObject, rather than
354  /// evaluating a compiled code instance.
355  static EvaluationResult evaluateCodeString(
356  int thread,
357  const UT_StringHolder& raw_code,
358  void*& result,
359  bool multi,
360  UT_WorkBuffer& errors);
361 
362  /// Saves a PyObject attribute to a string
363  static bool savePyObjectAttr(
364  int thread,
365  UT_StringHolder& result,
366  const PDG_AttributePyObject* attr,
367  const UT_StringHolder& module);
368 
369  /// Loads a PyObject attribute to a string
370  static bool loadPyObjectAttr(
371  int thread,
372  void*& result,
373  const UT_StringHolder& attr_data,
374  const UT_StringHolder& module);
375 
376  /// Cooks work item with the specified job script module
377  static bool cookWorkItem(
378  int thread,
379  const UT_StringHolder& module,
380  PDG_WorkItem* work_item,
381  UT_WorkBuffer& errors);
382 
383  /// Hashes a PyOvject attribute
384  static bool hashPyObjectAttr(
385  SYS_HashType& result,
386  const PDG_AttributePyObject* attr,
387  UT_WorkBuffer& errors);
388 
389  /// Updates parameter error state
390  static void updateParameterEvaluation(
391  int thread,
392  bool has_error);
393 
394 public:
395  /// Returns the context's active work item
396  const PDG_WorkItem* workItem() const;
397 
398  /// Returns true if the local work item is the parent item for the
399  /// evaluation
400  bool isParent() const;
401 
402  /// Returns the active node for the the context
403  const PDG_Node* activeNode() const;
404 
405  /// Returns the state of the context
406  State state() const;
407 
408  /// Returns the parameter evaluation state of the context
409  bool hasParameterError() const;
410 
411  /// Returns the current evaluation time of the context
412  fpreal evalTime() const;
413 
414  /// Returns true if the context is in a generating state
415  bool isGenerating() const
416  { return (myState == eStateStatic) ||
417  (myState == eStateDynamic); }
418 
419  /// Returns true if the context is in a cooking state
420  bool isCooking() const
421  { return (myState == eStateCooking); }
422 
423  /// Returns true if the context is in a runtime state
424  bool isRuntime() const
425  { return (myState == eStateDynamic) ||
426  (myState == eStateCooking) ||
427  (myState == eStateNone); }
428 
429 
430  /// Returns true if the context is actively doing PDG work
431  bool isActive() const
432  { return myState != eStateNone; }
433 
434  /// Returns true if the context should force file paths to be localized
435  bool isLocalize() const
436  { return myIsLocalize; }
437 
438  /// Returns true if the specified work item can be dirtied in the
439  /// current context
440  bool canDirty(const PDG_WorkItem* work_item) const;
441 
442  /// Returns true if the specified node can be dirtied in the current
443  /// context
444  bool canDirty(const PDG_Node* node) const;
445 
446  /// General version of the above method that can be called without a node
447  bool canDirty() const;
448 
449  /// Records an attribute access with the active scope block, if one has
450  /// been set
452  {
453  if (myAttributeRecord)
454  myAttributeRecord->record(name);
455  }
456 
457 private:
458  /// Internal initialize logic
459  void init();
460 
461  /// Internal reset logic
462  void reset();
463 
464  /// Returns the local dictionary
465  PY_PyObject* dict() const;
466 
467  /// Returns the context's local work item
468  const PDG_WorkItem* activeWorkItem() const;
469 
470  /// Returns the context's current attribute record block, or nullptr if
471  /// one has not been set.
472  AttribRecordScope* attributeRecord() const;
473 
474  /// Gets/Sets the local work item
475  void setWorkItem(const PDG_WorkItem* work_item,
476  bool parent);
477 
478  /// Sets the active node for the context
479  void setActiveNode(const PDG_Node* node);
480 
481  /// Sets the context state
482  void setState(State state);
483 
484  /// Sets the context parameter evaluation state
485  void setParameterError(bool has_error);
486 
487  /// Sets the context eval time
488  void setEvalTime(fpreal time);
489 
490  /// Sets the forced localization flag
491  void setLocalize(bool localize);
492 
493  /// Set the active attribute record scope
494  void setAttributeRecord(AttribRecordScope* scope);
495 
496  /// Adds an attribute evaluator to the map, or returns one if it already
497  /// exists. Templated so the caller can select the type
498  PDG_AttributeEvaluator* attributeEvaluator(const char* name);
499 
500  /// Generic evaluation method that returns the result of an expression in
501  /// a PY_Result object
502  EvaluationResult evaluate(const PY_CompiledCode& expression,
504  PY_Result& result,
505  bool include_details,
506  UT_WorkBuffer& errors);
507 
508  /// Sets the local dictionary. If the locals object is nullptr, resets the
509  /// dictionary to an empty dict
510  void setLocalDict(PY_PyObject* locals);
511 
512  /// Copies the local dict if it has modifications, else returns a nullptr
513  PY_PyObject* saveLocalDict();
514 
515  /// Restores and frees the local dict
516  void restoreLocalDict(PY_PyObject* locals);
517 
518  /// Sets a local dictionary entry by running a script
519  void setLocalDictEntryByScript(
520  const UT_StringHolder& name,
521  const char* py_expression);
522  /// Sets a local dictionary entry as a PyObject
523  void setLocalDictEntryByObject(
524  const UT_StringHolder& name,
525  PY_PyObject* py_obj);
526 
527 private:
529 
530  PY_PyObject* myLocalDict;
531  const PDG_WorkItem* myActiveWorkItem;
532  const PDG_Node* myActiveNode;
533  EvaluatorMap myAttributeMap;
534  AttribRecordScope* myAttributeRecord;
535  fpreal myEvalTime;
536 
537  State myState;
538 
539  bool myDictModified : 1;
540  bool myIsParent : 1;
541  bool myIsLocalize : 1;
542  bool myHasParameterError : 1;
543 };
544 
545 #endif
OIIO_API bool has_error()
Is there a pending global error message waiting to be retrieved?
void
Definition: png.h:1083
GT_API const UT_StringHolder time
#define PDG_API
Definition: PDG_API.h:23
State
Evaluation context state.
int64 exint
Definition: SYS_Types.h:125
std::size_t SYS_HashType
Define the type for hash values.
Definition: SYS_Hash.h:19
UT_Function< PY_PyObject *(const PDG_WorkItem *)> WorkItemCaster
Utility function type for converting a PDG_WorkItem* to a PY_PyObject.
**But if you need a result
Definition: thread.h:613
EvaluationResult
Enumeration of python script evaluation results.
bool isActive() const
Returns true if the context is actively doing PDG work.
Scoped setter of local work item.
GLboolean reset
Definition: glad.h:5138
The script succeeded without any exceptions.
PY_PyObject
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
The script encountered an error or exception.
bool isCooking() const
Returns true if the context is in a cooking state.
GLuint const GLchar * name
Definition: glcorearb.h:786
Scoped block that records PDG attribute evaluations.
std::function< T > UT_Function
Definition: UT_Function.h:37
**Note that the tasks the is the thread number *for the or if it s being executed by a non pool thread(this *can happen in cases where the whole pool is occupied and the calling *thread contributes to running the work load).**Thread pool.Have fun
fpreal64 fpreal
Definition: SYS_Types.h:277
GLuint index
Definition: glcorearb.h:786
bool isRuntime() const
Returns true if the context is in a runtime state.
Definition: core.h:1131
bool isLocalize() const
Returns true if the context should force file paths to be localized.
UT_ErrorManager::Scope UT_AutoErrorManager
Alias UT_AutoErrorManager as UT_ErrorManager::Scope.
Scoped reset of the thread-local context cooking/generation state.
type
Definition: core.h:1059
void recordAttribute(const UT_StringHolder &name)