mapExpression.h
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_USD_PCP_MAP_EXPRESSION_H
25 #define PXR_USD_PCP_MAP_EXPRESSION_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/pcp/api.h"
29 #include "pxr/usd/pcp/mapFunction.h"
30 
31 #include <boost/intrusive_ptr.hpp>
32 
33 #include <tbb/atomic.h>
34 #include <tbb/spin_mutex.h>
35 
36 #include <atomic>
37 #include <memory>
38 
39 PXR_NAMESPACE_OPEN_SCOPE
40 
57 {
58 public:
61 
66  PCP_API
67  const Value & Evaluate() const;
68 
70  PcpMapExpression() noexcept = default;
71 
73  void Swap(PcpMapExpression &other) noexcept {
74  _node.swap(other._node);
75  }
76 
78  bool IsNull() const noexcept {
79  return !_node;
80  }
81 
84 
86  PCP_API
87  static PcpMapExpression Identity();
88 
90  PCP_API
91  static PcpMapExpression Constant( const Value & constValue );
92 
96  class Variable {
97  Variable(Variable const &) = delete;
98  Variable &operator=(Variable const &) = delete;
99  public:
100  Variable() = default;
101  virtual ~Variable();
103  virtual const Value & GetValue() const = 0;
106  virtual void SetValue(Value && value) = 0;
109  virtual PcpMapExpression GetExpression() const = 0;
110  };
111 
113  typedef std::unique_ptr<Variable> VariableUniquePtr;
114 
121  PCP_API
122  static VariableUniquePtr NewVariable(Value && initialValue);
123 
126  PCP_API
127  PcpMapExpression Compose(const PcpMapExpression &f) const;
128 
130  PCP_API
131  PcpMapExpression Inverse() const;
132 
135  PCP_API
137 
139  bool IsConstantIdentity() const {
140  return _node && _node->key.op == _OpConstant &&
141  _node->key.valueForConstant.IsIdentity();
142  }
143 
145 
150 
153  bool IsIdentity() const {
154  return Evaluate().IsIdentity();
155  }
156 
159  SdfPath MapSourceToTarget(const SdfPath &path) const {
160  return Evaluate().MapSourceToTarget(path);
161  }
162 
165  SdfPath MapTargetToSource(const SdfPath &path) const {
166  return Evaluate().MapTargetToSource(path);
167  }
168 
170  const SdfLayerOffset &GetTimeOffset() const {
171  return Evaluate().GetTimeOffset();
172  }
173 
176  std::string GetString() const {
177  return Evaluate().GetString();
178  }
179 
181 
182 private:
183  // Allow Pcp_Statistics access to internal data for diagnostics.
184  friend class Pcp_Statistics;
185  friend struct Pcp_VariableImpl;
186 
187  class _Node;
188  typedef boost::intrusive_ptr<_Node> _NodeRefPtr;
189 
190  explicit PcpMapExpression(const _NodeRefPtr & node) : _node(node) {}
191 
192 private: // data
193  enum _Op {
194  _OpConstant,
195  _OpVariable,
196  _OpInverse,
197  _OpCompose,
198  _OpAddRootIdentity
199  };
200 
201  class _Node : public boost::noncopyable {
202  public:
203  // The Key holds all the state needed to uniquely identify
204  // this (sub-)expression.
205  struct Key {
206  const _Op op;
207  const _NodeRefPtr arg1, arg2;
208  const Value valueForConstant;
209 
210  Key( _Op op_,
211  const _NodeRefPtr & arg1_,
212  const _NodeRefPtr & arg2_,
213  const Value & valueForConstant_ )
214  : op(op_)
215  , arg1(arg1_)
216  , arg2(arg2_)
217  , valueForConstant(valueForConstant_)
218  {}
219  inline size_t GetHash() const;
220  bool operator==(const Key &key) const;
221  };
222 
223  // The Key of a node is const, and established when it is created.
224  const Key key;
225 
226  // Whether or not the expression tree up to and including this node
227  // will always include an identity mapping.
228  const bool expressionTreeAlwaysHasIdentity;
229 
230  // Factory method to create new nodes.
231  static _NodeRefPtr
232  New( _Op op,
233  const _NodeRefPtr & arg1 = _NodeRefPtr(),
234  const _NodeRefPtr & arg2 = _NodeRefPtr(),
235  const Value & valueForConstant = Value() );
236  ~_Node();
237 
238  // Evaluate (and internally cache) the value of this node.
239  const Value & EvaluateAndCache() const;
240 
241  // For _OpVariable nodes, sets the variable's value.
242  void SetValueForVariable(Value &&newValue);
243 
244  // For _OpVariable nodes, returns the variable's value.
245  const Value & GetValueForVariable() const {
246  return _valueForVariable;
247  }
248 
249  private:
250  explicit _Node( const Key &key_ );
251  void _Invalidate();
252  Value _EvaluateUncached() const;
253 
254  // Helper to determine if the expression tree indicated by key
255  // will always contains the root identity.
256  static bool _ExpressionTreeAlwaysHasIdentity(const Key& key);
257 
258  // Ref-counting ops manage _refCount.
259  // Need to friend them here to have access to _refCount.
260  friend PCP_API void intrusive_ptr_add_ref(_Node*);
261  friend PCP_API void intrusive_ptr_release(_Node*);
262 
263  // Registry of node instances, identified by Key.
264  // Note: variable nodes are not tracked by the registry.
265  struct _NodeMap;
266  static TfStaticData<_NodeMap> _nodeRegistry;
267 
268  mutable tbb::atomic<int> _refCount;
269  mutable Value _cachedValue;
270  mutable std::set<_Node*> _dependentExpressions;
271  Value _valueForVariable;
272  mutable tbb::spin_mutex _mutex;
273  mutable std::atomic<bool> _hasCachedValue;
274  };
275 
276  // Need to friend them here to have visibility to private class _Node.
277  friend PCP_API void intrusive_ptr_add_ref(_Node*);
278  friend PCP_API void intrusive_ptr_release(_Node*);
279 
280  _NodeRefPtr _node;
281 };
282 
283 PXR_NAMESPACE_CLOSE_SCOPE
284 
285 #endif // PXR_USD_PCP_MAP_EXPRESSION_H
PCP_API const Value & Evaluate() const
Evaluate this expression, yielding a PcpMapFunction value.
PCP_API PcpMapExpression Inverse() const
Create a new PcpMapExpression representing the inverse of f.
An expression that yields a PcpMapFunction value.
Definition: mapExpression.h:56
static PCP_API PcpMapExpression Identity()
Return an expression representing PcpMapFunction::Identity().
const SdfLayerOffset & GetTimeOffset() const
The time offset of the mapping.
Definition: mapFunction.h:176
PcpMapExpression() noexcept=default
Default-construct a NULL expression.
virtual const Value & GetValue() const =0
Return the current value.
static PCP_API VariableUniquePtr NewVariable(Value &&initialValue)
Create a new variable.
static PCP_API PcpMapExpression Constant(const Value &constValue)
Create a new constant.
SdfPath MapTargetToSource(const SdfPath &path) const
Map a path in the target namespace to the source.
PCP_API bool IsIdentity() const
Return true if the map function is the identity function.
SdfPath MapSourceToTarget(const SdfPath &path) const
Map a path in the source namespace to the target.
void Swap(PcpMapExpression &other) noexcept
Swap this expression with the other.
Definition: mapExpression.h:73
bool IsNull() const noexcept
Return true if this is a null expression.
Definition: mapExpression.h:78
PCP_API std::string GetString() const
Returns a string representation of this mapping for debugging purposes.
PcpMapFunction Value
The value type of PcpMapExpression is a PcpMapFunction.
Definition: mapExpression.h:60
A function that maps values from one namespace (and time domain) to another.
Definition: mapFunction.h:80
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
PCP_API SdfPath MapTargetToSource(const SdfPath &path) const
Map a path in the target namespace to the source.
A Variable is a mutable memory cell that holds a value.
Definition: mapExpression.h:96
std::string GetString() const
Returns a string representation of this mapping for debugging purposes.
PCP_API PcpMapExpression Compose(const PcpMapExpression &f) const
Create a new PcpMapExpression representing the application of f's value, followed by the application ...
bool IsConstantIdentity() const
Return true if the map function is the constant identity function.
PCP_API PcpMapExpression AddRootIdentity() const
Return a new expression representing this expression with an added (if necessary) mapping from </> to...
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
PCP_API SdfPath MapSourceToTarget(const SdfPath &path) const
Map a path in the source namespace to the target.
Represents a time offset and scale between layers.
Definition: layerOffset.h:61
virtual PcpMapExpression GetExpression() const =0
Return an expression representing the value of this variable.
bool IsIdentity() const
Return true if the evaluated map function is the identity function.
const SdfLayerOffset & GetTimeOffset() const
The time offset of the mapping.
virtual void SetValue(Value &&value)=0
Mutate the variable to have the new value.
std::unique_ptr< Variable > VariableUniquePtr
Variables are held by reference.