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