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 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"
30 
31 #include <hboost/intrusive_ptr.hpp>
32 
33 #include <tbb/atomic.h>
34 #include <tbb/spin_mutex.h>
35 
36 #include <atomic>
37 #include <memory>
38 
40 
41 /// \class PcpMapExpression
42 ///
43 /// An expression that yields a PcpMapFunction value.
44 ///
45 /// Expressions comprise constant values, variables, and operators
46 /// applied to sub-expressions. Expressions cache their computed values
47 /// internally. Assigning a new value to a variable automatically
48 /// invalidates the cached values of dependent expressions. Common
49 /// (sub-)expressions are automatically detected and shared.
50 ///
51 /// PcpMapExpression exists solely to support efficient incremental
52 /// handling of relocates edits. It represents a tree of the namespace
53 /// mapping operations and their inputs, so we can narrowly redo the
54 /// computation when one of the inputs changes.
55 ///
57 {
58 public:
59  /// The value type of PcpMapExpression is a PcpMapFunction.
61 
62  /// Evaluate this expression, yielding a PcpMapFunction value.
63  /// The computed result is cached.
64  /// The return value is a reference to the internal cached value.
65  /// The cache is automatically invalidated as needed.
66  PCP_API
67  const Value & Evaluate() const;
68 
69  /// Default-construct a NULL expression.
70  PcpMapExpression() noexcept = default;
71 
72  /// Swap this expression with the other.
73  void Swap(PcpMapExpression &other) noexcept {
74  _node.swap(other._node);
75  }
76 
77  /// Return true if this is a null expression.
78  bool IsNull() const noexcept {
79  return !_node;
80  }
81 
82  /// \name Creating expressions
83  /// @{
84 
85  /// Return an expression representing PcpMapFunction::Identity().
86  PCP_API
87  static PcpMapExpression Identity();
88 
89  /// Create a new constant.
90  PCP_API
91  static PcpMapExpression Constant( const Value & constValue );
92 
93  /// A Variable is a mutable memory cell that holds a value.
94  /// Changing a variable's value invalidates any expressions using
95  /// that variable.
96  class Variable {
97  Variable(Variable const &) = delete;
98  Variable &operator=(Variable const &) = delete;
99  public:
100  Variable() = default;
101  virtual ~Variable();
102  /// Return the current value.
103  virtual const Value & GetValue() const = 0;
104  /// Mutate the variable to have the new value.
105  /// This will also invalidate dependant expressions.
106  virtual void SetValue(Value && value) = 0;
107  /// Return an expression representing the value of this variable.
108  /// This lets you use the variable as a sub-term in other expressions.
109  virtual PcpMapExpression GetExpression() const = 0;
110  };
111 
112  /// Variables are held by reference.
113  typedef std::unique_ptr<Variable> VariableUniquePtr;
114 
115  /// Create a new variable.
116  /// The client is expected to retain the reference for as long as
117  /// it wishes to continue being able to set the value of the variable.
118  /// After the reference is dropped, expressions using the variable
119  /// will continue to be valid, but there will be no way to further
120  /// change the value of the variable.
121  PCP_API
122  static VariableUniquePtr NewVariable(Value && initialValue);
123 
124  /// Create a new PcpMapExpression representing the application of
125  /// f's value, followed by the application of this expression's value.
126  PCP_API
128 
129  /// Create a new PcpMapExpression representing the inverse of f.
130  PCP_API
131  PcpMapExpression Inverse() const;
132 
133  /// Return a new expression representing this expression with an added
134  /// (if necessary) mapping from </> to </>.
135  PCP_API
137 
138  /// Return true if the map function is the constant identity function.
139  bool IsConstantIdentity() const {
140  return _node && _node->key.op == _OpConstant &&
141  _node->key.valueForConstant.IsIdentity();
142  }
143 
144  /// @}
145 
146  /// \name Convenience API
147  /// The following API just forwards through to the underlying evaluated
148  /// mapfunction value.
149  /// @{
150 
151  /// Return true if the evaluated map function is the identity function.
152  /// For identity, MapSourceToTarget() always returns the path unchanged.
153  bool IsIdentity() const {
154  return Evaluate().IsIdentity();
155  }
156 
157  /// Map a path in the source namespace to the target.
158  /// If the path is not in the domain, returns an empty path.
160  return Evaluate().MapSourceToTarget(path);
161  }
162 
163  /// Map a path in the target namespace to the source.
164  /// If the path is not in the co-domain, returns an empty path.
166  return Evaluate().MapTargetToSource(path);
167  }
168 
169  /// The time offset of the mapping.
170  const SdfLayerOffset &GetTimeOffset() const {
171  return Evaluate().GetTimeOffset();
172  }
173 
174  /// Returns a string representation of this mapping for debugging
175  /// purposes.
177  return Evaluate().GetString();
178  }
179 
180  /// @}
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 hboost::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 {
202  _Node(const _Node&) = delete;
203  _Node& operator=(const _Node&) = delete;
204  public:
205  // The Key holds all the state needed to uniquely identify
206  // this (sub-)expression.
207  struct Key {
208  const _Op op;
209  const _NodeRefPtr arg1, arg2;
211 
212  Key( _Op op_,
213  const _NodeRefPtr & arg1_,
214  const _NodeRefPtr & arg2_,
215  const Value & valueForConstant_ )
216  : op(op_)
217  , arg1(arg1_)
218  , arg2(arg2_)
219  , valueForConstant(valueForConstant_)
220  {}
221  inline size_t GetHash() const;
222  bool operator==(const Key &key) const;
223  };
224 
225  // The Key of a node is const, and established when it is created.
226  const Key key;
227 
228  // Whether or not the expression tree up to and including this node
229  // will always include an identity mapping.
230  const bool expressionTreeAlwaysHasIdentity;
231 
232  // Factory method to create new nodes.
233  static _NodeRefPtr
234  New( _Op op,
235  const _NodeRefPtr & arg1 = _NodeRefPtr(),
236  const _NodeRefPtr & arg2 = _NodeRefPtr(),
237  const Value & valueForConstant = Value() );
238  ~_Node();
239 
240  // Evaluate (and internally cache) the value of this node.
241  const Value & EvaluateAndCache() const;
242 
243  // For _OpVariable nodes, sets the variable's value.
244  void SetValueForVariable(Value &&newValue);
245 
246  // For _OpVariable nodes, returns the variable's value.
247  const Value & GetValueForVariable() const {
248  return _valueForVariable;
249  }
250 
251  private:
252  explicit _Node( const Key &key_ );
253  void _Invalidate();
254  Value _EvaluateUncached() const;
255 
256  // Helper to determine if the expression tree indicated by key
257  // will always contains the root identity.
258  static bool _ExpressionTreeAlwaysHasIdentity(const Key& key);
259 
260  // Ref-counting ops manage _refCount.
261  // Need to friend them here to have access to _refCount.
262  friend PCP_API void intrusive_ptr_add_ref(_Node*);
263  friend PCP_API void intrusive_ptr_release(_Node*);
264 
265  // Registry of node instances, identified by Key.
266  // Note: variable nodes are not tracked by the registry.
267  struct _NodeMap;
268  static TfStaticData<_NodeMap> _nodeRegistry;
269 
270  mutable tbb::atomic<int> _refCount;
271  mutable Value _cachedValue;
272  mutable std::set<_Node*> _dependentExpressions;
273  Value _valueForVariable;
274  mutable tbb::spin_mutex _mutex;
275  mutable std::atomic<bool> _hasCachedValue;
276  };
277 
278  // Need to friend them here to have visibility to private class _Node.
279  friend PCP_API void intrusive_ptr_add_ref(_Node*);
280  friend PCP_API void intrusive_ptr_release(_Node*);
281 
282  _NodeRefPtr _node;
283 };
284 
286 
287 #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:60
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.
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 GLchar *const * string
Definition: glcorearb.h:814
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.
friend PCP_API void intrusive_ptr_add_ref(_Node *)
const SdfLayerOffset & GetTimeOffset() const
The time offset of the mapping.
Definition: mapFunction.h:176
virtual PcpMapExpression GetExpression() const =0
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:44
SdfPath MapSourceToTarget(const SdfPath &path) const
virtual void SetValue(Value &&value)=0
std::unique_ptr< Variable > VariableUniquePtr
Variables are held by reference.
Definition: path.h:291
PCP_API const Value & Evaluate() const
bool operator==(const Key &key) 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:1441
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
friend PCP_API void intrusive_ptr_release(_Node *)
bool IsNull() const noexcept
Return true if this is a null expression.
Definition: mapExpression.h:78
Definition: core.h:1131
#define const
Definition: zconf.h:214
PcpMapExpression() noexcept=default
Default-construct a NULL expression.
PCP_API std::string GetString() const
PCP_API SdfPath MapTargetToSource(const SdfPath &path) const
static PCP_API PcpMapExpression Constant(const Value &constValue)
Create a new constant.
friend class Pcp_Statistics
#define PCP_API
Definition: api.h:40
void Swap(PcpMapExpression &other) noexcept
Swap this expression with the other.
Definition: mapExpression.h:73