HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
declareHandles.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_SDF_DECLARE_HANDLES_H
25 #define PXR_USD_SDF_DECLARE_HANDLES_H
26 
27 /// \file sdf/declareHandles.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/api.h"
31 #include "pxr/base/arch/demangle.h"
32 #include "pxr/base/arch/hints.h"
33 #include "pxr/base/tf/diagnostic.h"
36 
37 #include <set>
38 #include <typeinfo>
39 #include <type_traits>
40 #include <vector>
41 #include <hboost/intrusive_ptr.hpp>
42 
44 
45 class SdfLayer;
46 class SdfSpec;
47 template <class T> class TfRefPtr;
49 
50 // Sdf_Identities are held via intrusive_ptr so that we can carefully
51 // manage the ref-count to avoid race conditions -- see
52 // Sdf_IdentityRegistry::Identify().
53 typedef hboost::intrusive_ptr<Sdf_Identity> Sdf_IdentityRefPtr;
54 
55 /// \class SdfHandle
56 ///
57 /// SdfHandle is a smart ptr that calls IsDormant() on the pointed-to
58 /// object as an extra expiration check so that dormant objects appear to
59 /// be expired.
60 ///
61 template <class T>
62 class SdfHandle {
63 public:
64  typedef SdfHandle<T> This;
65  typedef T SpecType;
66 
69 
70  SdfHandle() { }
72  explicit SdfHandle(const Sdf_IdentityRefPtr& id) : _spec(id) { }
73  SdfHandle(const SpecType& spec) : _spec(spec) { }
74 
75  template <class U>
76  SdfHandle(const SdfHandle<U>& x) : _spec(x._spec) { }
77 
78  This& operator=(const This& x)
79  {
80  const_cast<NonConstSpecType&>(_spec) = x._spec;
81  return *this;
82  }
83 
84  template <class U>
86  {
87  const_cast<NonConstSpecType&>(_spec) = x._spec;
88  return *this;
89  }
90 
91  /// Dereference. Raises a fatal error if the object is invalid or
92  /// dormant.
94  {
95  if (ARCH_UNLIKELY(_spec.IsDormant())) {
96  TF_FATAL_ERROR("Dereferenced an invalid %s",
97  ArchGetDemangled(typeid(SpecType)).c_str());
98  return 0;
99  }
100  return const_cast<SpecType*>(&_spec);
101  }
102 
103  const SpecType & GetSpec() const
104  {
105  return _spec;
106  }
107 
108  void Reset()
109  {
110  const_cast<SpecType&>(_spec) = SpecType();
111  }
112 
113 #if !defined(doxygen)
115 #endif
116 
117  /// Returns \c true in a boolean context if the object is valid,
118  /// \c false otherwise.
119  operator UnspecifiedBoolType() const
120  {
121  return _spec.IsDormant() ? 0 : &This::_spec;
122  }
123  /// Returns \c false in a boolean context if the object is valid,
124  /// \c true otherwise.
125  bool operator!() const
126  {
127  return _spec.IsDormant();
128  }
129 
130  /// Compares handles for equality.
131  template <class U>
132  bool operator==(const SdfHandle<U>& other) const
133  {
134  return _spec == other._spec;
135  }
136 
137  /// \sa SdfHandle::operator==
138  friend bool operator!=(const SdfHandle& lhs, const SdfHandle& rhs)
139  {
140  return !(lhs == rhs);
141  }
142 
143  /// Arranges handles in an arbitrary strict weak ordering. Note that
144  /// this ordering is stable across path changes.
145  template <class U>
146  bool operator<(const SdfHandle<U>& other) const
147  {
148  return _spec < other._spec;
149  }
150 
151  /// \sa SdfHandle::operator<
152  friend bool operator>(const SdfHandle& lhs, const SdfHandle& rhs)
153  {
154  return rhs < lhs;
155  }
156 
157  /// \sa SdfHandle::operator<
158  friend bool operator<=(const SdfHandle& lhs, const SdfHandle& rhs)
159  {
160  return !(rhs < lhs);
161  }
162 
163  /// \sa SdfHandle::operator<
164  friend bool operator>=(const SdfHandle& lhs, const SdfHandle& rhs)
165  {
166  return !(lhs < rhs);
167  }
168 
169  /// Hash.
170  friend size_t hash_value(const This &x) {
171  return hash_value(x._spec);
172  }
173 
174 private:
175  friend
176  inline SpecType *get_pointer(const SdfHandle &x) {
177  return ARCH_UNLIKELY(x._spec.IsDormant()) ?
178  nullptr : const_cast<SpecType*>(&x._spec);
179  }
180 
181  SpecType _spec;
182 
183  template <class U> friend class SdfHandle;
184 };
185 
187 
188 namespace hboost {
189 
190 using PXR_NS::get_pointer;
191 
192 }
193 
195 
196 template <class T>
197 struct SdfHandleTo {
200  typedef std::vector<Handle> Vector;
201  typedef std::vector<ConstHandle> ConstVector;
202 };
203 
204 template <>
208  typedef std::vector<Handle> Vector;
209  typedef std::vector<ConstHandle> ConstVector;
210 };
211 
212 template <typename T>
213 typename SdfHandleTo<T>::Handle
215 {
216  return typename SdfHandleTo<T>::Handle(p ? *p : T());
217 }
218 
219 template <>
222 
223 template <typename T>
224 typename SdfHandleTo<T>::Handle
226 {
227  return SdfCreateHandle(const_cast<T *>(p));
228 }
229 
231  template<class DST, class SRC>
232  static DST CastSpec(const SRC& spec) {
233  return DST(spec);
234  }
235 };
236 
237 SDF_API bool
239  const SdfSpec& srcSpec, const std::type_info& destType);
240 
241 SDF_API bool
243  const SdfSpec& srcSpec, const std::type_info& destType);
244 
245 template <class DST, class SRC>
247  : std::integral_constant<bool,
248  std::is_base_of<DST, SRC>::value ||
249  std::is_base_of<SRC, DST>::value>
250 { };
251 
252 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
253 /// behaves similar to a dynamic_cast. If class DST cannot represent
254 /// the spec pointed to be \p x, or if the classes DST and SRC are
255 /// not directly related to each other in the C++ type hierarchy,
256 /// the conversion fails and an invalid handle is returned.
257 ///
258 /// XXX: The second condition in the above statement is currently untrue.
259 /// This function will allow casting between spec classes even if
260 /// they are not directly related. Doing so could lead to schema
261 /// mismatches and other buggy behavior.
262 template <typename DST, typename SRC>
263 inline
266 {
267  typedef typename DST::SpecType Spec;
268  typedef SdfHandle<Spec> Handle;
269 
270  if (Sdf_CanCastToType(x.GetSpec(), typeid(Spec))) {
271  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
272  }
273 
274  return Handle();
275 }
276 
277 template <typename DST, typename SRC>
278 inline
281 {
282  return TfDynamic_cast(x);
283 }
284 
285 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
286 /// behaves similar to a static_cast. No runtime checks are performed
287 /// to ensure the conversion is valid; it is up to the consumer to
288 /// ensure this.
289 template <typename DST, typename SRC>
290 inline
293 {
294  typedef typename DST::SpecType Spec;
295  typedef SdfHandle<Spec> Handle;
297  "Spec and SRC must be directly related.");
298 
299  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
300 }
301 
302 template <typename T>
303 inline
306 {
307  return TfStatic_cast<T>(x);
308 }
309 
310 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
311 /// similar to TfDynamic_cast, but it allows the SRC and DST spec to be
312 /// indirectly related, so long as the schema associated with the DST
313 /// spec type is a subclass of the schema associated with \p x.
314 template <typename DST, typename SRC>
315 inline
318 {
319  typedef typename DST::SpecType Spec;
320  typedef SdfHandle<Spec> Handle;
321 
322  if (Sdf_CanCastToTypeCheckSchema(x.GetSpec(), typeid(Spec))) {
323  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
324  }
325 
326  return Handle();
327 }
328 
329 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
330 /// similar to TfStatic_cast, but it allows the SRC and DST spec to be
331 /// indirectly related.
332 template <typename DST, typename SRC>
333 inline
336 {
337  typedef typename DST::SpecType Spec;
338  typedef SdfHandle<Spec> Handle;
339  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
340 }
341 
342 /// Convert SRC_SPEC to a DST_SPEC.
343 template <typename DST_SPEC, typename SRC_SPEC>
344 inline
345 DST_SPEC
346 SdfSpecStatic_cast(const SRC_SPEC& x)
347 {
348  return Sdf_CastAccess::CastSpec<DST_SPEC,SRC_SPEC>(x);
349 }
350 
352 typedef std::vector<TfRefPtr<SdfLayer> > SdfLayerRefPtrVector;
354 
355 #define SDF_DECLARE_HANDLES(cls) \
356  typedef SdfHandleTo<class cls>::Handle cls##Handle; \
357  typedef SdfHandleTo<class cls>::ConstHandle cls##ConstHandle; \
358  typedef SdfHandleTo<class cls>::Vector cls##HandleVector; \
359  typedef SdfHandleTo<class cls>::ConstVector cls##ConstHandleVector
360 
362 
363 #endif // PXR_USD_SDF_DECLARE_HANDLES_H
friend bool operator>=(const SdfHandle &lhs, const SdfHandle &rhs)
SdfHandle(const SpecType &spec)
Definition: layer.h:97
std::vector< ConstHandle > ConstVector
SdfHandle< NonConstSpecType > NonConstThis
SdfHandle< typename DST::SpecType > TfStatic_cast(const SdfHandle< SRC > &x)
SdfHandleTo< T >::Handle SdfCreateHandle(T *p)
SpecType * operator->() const
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
Definition: spec.h:49
SdfHandle< T > Handle
std::set< SdfHandleTo< SdfLayer >::Handle > SdfLayerHandleSet
TfWeakPtr< SdfLayer > Handle
hboost::intrusive_ptr< Sdf_Identity > Sdf_IdentityRefPtr
SdfHandle< typename DST::SpecType > TfSafeDynamic_cast(const SdfHandle< SRC > &x)
Y * get_pointer(TfWeakPtrFacade< X, Y > const &p)
Definition: weakPtrFacade.h:83
std::vector< ConstHandle > ConstVector
friend bool operator<=(const SdfHandle &lhs, const SdfHandle &rhs)
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
std::vector< Handle > Vector
std::vector< TfRefPtr< SdfLayer > > SdfLayerRefPtrVector
SdfHandle< typename DST::SpecType > TfDynamic_cast(const SdfHandle< SRC > &x)
friend SpecType * get_pointer(const SdfHandle &x)
static DST CastSpec(const SRC &spec)
#define TF_FATAL_ERROR
friend bool operator>(const SdfHandle &lhs, const SdfHandle &rhs)
SDF_API bool Sdf_CanCastToTypeCheckSchema(const SdfSpec &srcSpec, const std::type_info &destType)
SdfHandle< typename DST::SpecType > SdfSpecDynamic_cast(const SdfHandle< SRC > &x)
std::remove_const< SpecType >::type NonConstSpecType
SdfHandle< T > This
GLint GLenum GLint x
Definition: glcorearb.h:409
SDF_API bool Sdf_CanCastToType(const SdfSpec &srcSpec, const std::type_info &destType)
SdfHandle(const SdfHandle< U > &x)
#define SDF_API
Definition: api.h:40
bool operator!() const
SdfHandleTo< T >::Handle SdfCreateNonConstHandle(T const *p)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
friend bool operator!=(const SdfHandle &lhs, const SdfHandle &rhs)
SdfHandle(const Sdf_IdentityRefPtr &id)
This & operator=(const SdfHandle< U > &x)
TfWeakPtr< const SdfLayer > ConstHandle
SdfHandle< typename T::SpecType > TfConst_cast(const SdfHandle< const typename T::SpecType > &x)
SpecType This::* UnspecifiedBoolType
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
SdfHandle(TfNullPtrType)
SdfHandle< const T > ConstHandle
const SpecType & GetSpec() const
TfRefPtr< SdfLayer > SdfLayerRefPtr
std::vector< Handle > Vector
void Reset()
friend size_t hash_value(const This &x)
Hash.
type
Definition: core.h:1059
SdfHandle< typename DST::SpecType > SdfSpecStatic_cast(const SdfHandle< SRC > &x)
bool operator==(const SdfHandle< U > &other) const
Compares handles for equality.
This & operator=(const This &x)
void * Handle
Definition: plugin.h:27