HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mapExpression.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_PCP_MAP_EXPRESSION_H
8 #define PXR_USD_PCP_MAP_EXPRESSION_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/usd/pcp/api.h"
13 
15 
16 #include <tbb/spin_mutex.h>
17 
18 #include <atomic>
19 #include <memory>
20 
22 
23 /// \class PcpMapExpression
24 ///
25 /// An expression that yields a PcpMapFunction value.
26 ///
27 /// Expressions comprise constant values, variables, and operators
28 /// applied to sub-expressions. Expressions cache their computed values
29 /// internally. Assigning a new value to a variable automatically
30 /// invalidates the cached values of dependent expressions. Common
31 /// (sub-)expressions are automatically detected and shared.
32 ///
33 /// PcpMapExpression exists solely to support efficient incremental
34 /// handling of relocates edits. It represents a tree of the namespace
35 /// mapping operations and their inputs, so we can narrowly redo the
36 /// computation when one of the inputs changes.
37 ///
39 {
40 public:
41  /// The value type of PcpMapExpression is a PcpMapFunction.
43 
44  /// Evaluate this expression, yielding a PcpMapFunction value.
45  /// The computed result is cached.
46  /// The return value is a reference to the internal cached value.
47  /// The cache is automatically invalidated as needed.
48  PCP_API
49  const Value & Evaluate() const;
50 
51  /// Default-construct a NULL expression.
52  PcpMapExpression() noexcept = default;
53 
54  ~PcpMapExpression() noexcept = default;
55 
56  /// Swap this expression with the other.
57  void Swap(PcpMapExpression &other) noexcept {
58  _node.swap(other._node);
59  }
60 
61  /// Return true if this is a null expression.
62  bool IsNull() const noexcept {
63  return !_node;
64  }
65 
66  /// \name Creating expressions
67  /// @{
68 
69  /// Return an expression representing PcpMapFunction::Identity().
70  PCP_API
71  static PcpMapExpression Identity();
72 
73  /// Create a new constant.
74  PCP_API
75  static PcpMapExpression Constant( const Value & constValue );
76 
77  /// A Variable is a mutable memory cell that holds a value.
78  /// Changing a variable's value invalidates any expressions using
79  /// that variable.
80  class Variable {
81  Variable(Variable const &) = delete;
82  Variable &operator=(Variable const &) = delete;
83  public:
84  Variable() = default;
85  virtual ~Variable();
86  /// Return the current value.
87  virtual const Value & GetValue() const = 0;
88  /// Mutate the variable to have the new value.
89  /// This will also invalidate dependant expressions.
90  virtual void SetValue(Value && value) = 0;
91  /// Return an expression representing the value of this variable.
92  /// This lets you use the variable as a sub-term in other expressions.
93  virtual PcpMapExpression GetExpression() const = 0;
94  };
95 
96  /// Variables are held by reference.
97  typedef std::unique_ptr<Variable> VariableUniquePtr;
98 
99  /// Create a new variable.
100  /// The client is expected to retain the reference for as long as
101  /// it wishes to continue being able to set the value of the variable.
102  /// After the reference is dropped, expressions using the variable
103  /// will continue to be valid, but there will be no way to further
104  /// change the value of the variable.
105  PCP_API
106  static VariableUniquePtr NewVariable(Value && initialValue);
107 
108  /// Create a new PcpMapExpression representing the application of
109  /// f's value, followed by the application of this expression's value.
110  PCP_API
112 
113  /// Create a new PcpMapExpression representing the inverse of f.
114  PCP_API
115  PcpMapExpression Inverse() const;
116 
117  /// Return a new expression representing this expression with an added
118  /// (if necessary) mapping from </> to </>.
119  PCP_API
121 
122  /// Return true if the map function is the constant identity function.
123  bool IsConstantIdentity() const {
124  return _node && _node->key.op == _OpConstant &&
125  _node->key.valueForConstant.IsIdentity();
126  }
127 
128  /// @}
129 
130  /// \name Convenience API
131  /// The following API just forwards through to the underlying evaluated
132  /// mapfunction value.
133  /// @{
134 
135  /// Return true if the evaluated map function is the identity function.
136  /// For identity, MapSourceToTarget() always returns the path unchanged.
137  bool IsIdentity() const {
138  return Evaluate().IsIdentity();
139  }
140 
141  /// Map a path in the source namespace to the target.
142  /// If the path is not in the domain, returns an empty path.
144  return Evaluate().MapSourceToTarget(path);
145  }
146 
147  /// Map a path in the target namespace to the source.
148  /// If the path is not in the co-domain, returns an empty path.
150  return Evaluate().MapTargetToSource(path);
151  }
152 
153  /// The time offset of the mapping.
154  const SdfLayerOffset &GetTimeOffset() const {
155  return Evaluate().GetTimeOffset();
156  }
157 
158  /// Returns a string representation of this mapping for debugging
159  /// purposes.
160  std::string GetString() const {
161  return Evaluate().GetString();
162  }
163 
164  /// @}
165 
166 private:
167  // Allow Pcp_Statistics access to internal data for diagnostics.
168  friend class Pcp_Statistics;
169  friend struct Pcp_VariableImpl;
170 
171  class _Node;
173 
174  explicit PcpMapExpression(const _NodeRefPtr & node) : _node(node) {}
175 
176 private: // data
177  enum _Op {
178  _OpConstant,
179  _OpVariable,
180  _OpInverse,
181  _OpCompose,
182  _OpAddRootIdentity
183  };
184 
185  class _Node {
186  _Node(const _Node&) = delete;
187  _Node& operator=(const _Node&) = delete;
188 
189  // Ref-counting ops manage _refCount.
190  // Need to friend them here to have access to _refCount.
191  friend PCP_API void TfDelegatedCountIncrement(_Node*);
192  friend PCP_API void TfDelegatedCountDecrement(_Node*) noexcept;
193  public:
194  // The Key holds all the state needed to uniquely identify
195  // this (sub-)expression.
196  struct Key {
197  const _Op op;
198  const _NodeRefPtr arg1, arg2;
200 
201  Key( _Op op_,
202  const _NodeRefPtr & arg1_,
203  const _NodeRefPtr & arg2_,
204  const Value & valueForConstant_ )
205  : op(op_)
206  , arg1(arg1_)
207  , arg2(arg2_)
208  , valueForConstant(valueForConstant_)
209  {}
210  inline size_t GetHash() const;
211  bool operator==(const Key &key) const;
212  };
213 
214  // The Key of a node is const, and established when it is created.
215  const Key key;
216 
217  // Whether or not the expression tree up to and including this node
218  // will always include an identity mapping.
219  const bool expressionTreeAlwaysHasIdentity;
220 
221  // Factory method to create new nodes.
222  static _NodeRefPtr
223  New( _Op op,
224  const _NodeRefPtr & arg1 = _NodeRefPtr(),
225  const _NodeRefPtr & arg2 = _NodeRefPtr(),
226  const Value & valueForConstant = Value() );
227  ~_Node();
228 
229  // Evaluate (and internally cache) the value of this node.
230  const Value & EvaluateAndCache() const;
231 
232  // For _OpVariable nodes, sets the variable's value.
233  void SetValueForVariable(Value &&newValue);
234 
235  // For _OpVariable nodes, returns the variable's value.
236  const Value & GetValueForVariable() const {
237  return _valueForVariable;
238  }
239 
240  private:
241  explicit _Node( const Key &key_ );
242  void _Invalidate();
243  Value _EvaluateUncached() const;
244 
245  // Helper to determine if the expression tree indicated by key
246  // will always contains the root identity.
247  static bool _ExpressionTreeAlwaysHasIdentity(const Key& key);
248 
249  // Registry of node instances, identified by Key.
250  // Note: variable nodes are not tracked by the registry.
251  struct _NodeMap;
252  static TfStaticData<_NodeMap> _nodeRegistry;
253 
254  mutable std::atomic<int> _refCount;
255  mutable Value _cachedValue;
256  mutable std::set<_Node*> _dependentExpressions;
257  Value _valueForVariable;
258  mutable tbb::spin_mutex _mutex;
259  mutable std::atomic<bool> _hasCachedValue;
260  };
261 
262  // Need to friend them here to have visibility to private class _Node.
263  friend PCP_API void TfDelegatedCountIncrement(_Node*);
264  friend PCP_API void TfDelegatedCountDecrement(_Node*) noexcept;
265 
266  _NodeRefPtr _node;
267 };
268 
270 
271 #endif // PXR_USD_PCP_MAP_EXPRESSION_H
Key(_Op op_, const _NodeRefPtr &arg1_, const _NodeRefPtr &arg2_, const Value &valueForConstant_)
PcpMapFunction Value
The value type of PcpMapExpression is a PcpMapFunction.
Definition: mapExpression.h:42
friend struct Pcp_VariableImpl
static PCP_API VariableUniquePtr NewVariable(Value &&initialValue)
bool IsConstantIdentity() const
Return true if the map function is the constant identity function.
friend PCP_API void TfDelegatedCountDecrement(_Node *) noexcept
PCP_API bool IsIdentity() const
static PCP_API PcpMapExpression Identity()
Return an expression representing PcpMapFunction::Identity().
PCP_API PcpMapExpression Compose(const PcpMapExpression &f) const
GLsizei const GLfloat * value
Definition: glcorearb.h:824
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
PCP_API SdfPath MapSourceToTarget(const SdfPath &path) const
PCP_API PcpMapExpression AddRootIdentity() const
virtual const Value & GetValue() const =0
Return the current value.
const SdfLayerOffset & GetTimeOffset() const
The time offset of the mapping.
Definition: mapFunction.h:206
virtual PcpMapExpression GetExpression() const =0
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
SdfPath MapTargetToSource(const SdfPath &path) const
GLfloat f
Definition: glcorearb.h:1926
std::string GetString() const
const SdfLayerOffset & GetTimeOffset() const
The time offset of the mapping.
A generic, discriminated value, whose type may be queried dynamically.
Definition: Value.h:45
SdfPath MapSourceToTarget(const SdfPath &path) const
virtual void SetValue(Value &&value)=0
std::unique_ptr< Variable > VariableUniquePtr
Variables are held by reference.
Definition: mapExpression.h:97
Definition: path.h:273
PCP_API const Value & Evaluate() const
bool IsIdentity() const
PCP_API PcpMapExpression Inverse() const
Create a new PcpMapExpression representing the inverse of f.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
LeafData & operator=(const LeafData &)=delete
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
bool IsNull() const noexcept
Return true if this is a null expression.
Definition: mapExpression.h:62
PcpMapExpression() noexcept=default
Default-construct a NULL expression.
PCP_API std::string GetString() const
PCP_API SdfPath MapTargetToSource(const SdfPath &path) const
friend PCP_API void TfDelegatedCountIncrement(_Node *)
static PCP_API PcpMapExpression Constant(const Value &constValue)
Create a new constant.
void swap(TfDelegatedCountPtr &other) noexcept
Swap this object's held pointer with other's.
friend class Pcp_Statistics
#define PCP_API
Definition: api.h:23
void Swap(PcpMapExpression &other) noexcept
Swap this expression with the other.
Definition: mapExpression.h:57