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 terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_USD_SDF_DECLARE_HANDLES_H
8 #define PXR_USD_SDF_DECLARE_HANDLES_H
9 
10 /// \file sdf/declareHandles.h
11 
12 #include "pxr/pxr.h"
13 #include "pxr/usd/sdf/api.h"
14 #include "pxr/base/arch/demangle.h"
15 #include "pxr/base/arch/hints.h"
17 #include "pxr/base/tf/diagnostic.h"
20 
21 #include <set>
22 #include <typeinfo>
23 #include <type_traits>
24 #include <vector>
25 
27 
28 class SdfLayer;
29 class SdfSpec;
30 template <class T> class TfRefPtr;
31 class Sdf_Identity;
32 
33 // Sdf_Identities are held via TfDelegatedCountPtr so that we can carefully
34 // manage the ref-count to avoid race conditions -- see
35 // Sdf_IdentityRegistry::Identify().
37 
38 /// \class SdfHandle
39 ///
40 /// SdfHandle is a smart ptr that calls IsDormant() on the pointed-to
41 /// object as an extra expiration check so that dormant objects appear to
42 /// be expired.
43 ///
44 template <class T>
45 class SdfHandle {
46 public:
47  typedef SdfHandle<T> This;
48  typedef T SpecType;
49 
52 
53  SdfHandle() { }
55  explicit SdfHandle(const Sdf_IdentityRefPtr& id) : _spec(id) { }
56  SdfHandle(const SpecType& spec) : _spec(spec) { }
57 
58  template <class U>
59  SdfHandle(const SdfHandle<U>& x) : _spec(x._spec) { }
60 
61  This& operator=(const This& x)
62  {
63  const_cast<NonConstSpecType&>(_spec) = x._spec;
64  return *this;
65  }
66 
67  template <class U>
69  {
70  const_cast<NonConstSpecType&>(_spec) = x._spec;
71  return *this;
72  }
73 
74  /// Dereference. Raises a fatal error if the object is invalid or
75  /// dormant.
77  {
78  if (ARCH_UNLIKELY(_spec.IsDormant())) {
79  TF_FATAL_ERROR("Dereferenced an invalid %s",
80  ArchGetDemangled(typeid(SpecType)).c_str());
81  return 0;
82  }
83  return const_cast<SpecType*>(&_spec);
84  }
85 
86  const SpecType & GetSpec() const
87  {
88  return _spec;
89  }
90 
91  void Reset()
92  {
93  const_cast<SpecType&>(_spec) = SpecType();
94  }
95 
96 #if !defined(doxygen)
98 #endif
99 
100  /// Returns \c true in a boolean context if the object is valid,
101  /// \c false otherwise.
102  operator UnspecifiedBoolType() const
103  {
104  return _spec.IsDormant() ? 0 : &This::_spec;
105  }
106  /// Returns \c false in a boolean context if the object is valid,
107  /// \c true otherwise.
108  bool operator!() const
109  {
110  return _spec.IsDormant();
111  }
112 
113  /// Compares handles for equality.
114  template <class U>
115  bool operator==(const SdfHandle<U>& other) const
116  {
117  return _spec == other._spec;
118  }
119 
120  /// \sa SdfHandle::operator==
121  friend bool operator!=(const SdfHandle& lhs, const SdfHandle& rhs)
122  {
123  return !(lhs == rhs);
124  }
125 
126  /// Arranges handles in an arbitrary strict weak ordering. Note that
127  /// this ordering is stable across path changes.
128  template <class U>
129  bool operator<(const SdfHandle<U>& other) const
130  {
131  return _spec < other._spec;
132  }
133 
134  /// \sa SdfHandle::operator<
135  friend bool operator>(const SdfHandle& lhs, const SdfHandle& rhs)
136  {
137  return rhs < lhs;
138  }
139 
140  /// \sa SdfHandle::operator<
141  friend bool operator<=(const SdfHandle& lhs, const SdfHandle& rhs)
142  {
143  return !(rhs < lhs);
144  }
145 
146  /// \sa SdfHandle::operator<
147  friend bool operator>=(const SdfHandle& lhs, const SdfHandle& rhs)
148  {
149  return !(lhs < rhs);
150  }
151 
152  /// Hash.
153  friend size_t hash_value(const This &x) {
154  return hash_value(x._spec);
155  }
156 
157 private:
158  friend
159  inline SpecType *get_pointer(const SdfHandle &x) {
160  return ARCH_UNLIKELY(x._spec.IsDormant()) ?
161  nullptr : const_cast<SpecType*>(&x._spec);
162  }
163 
164  SpecType _spec;
165 
166  template <class U> friend class SdfHandle;
167 };
168 
169 template <class T>
170 struct SdfHandleTo {
173  typedef std::vector<Handle> Vector;
174  typedef std::vector<ConstHandle> ConstVector;
175 };
176 
177 template <>
181  typedef std::vector<Handle> Vector;
182  typedef std::vector<ConstHandle> ConstVector;
183 };
184 
185 template <typename T>
186 typename SdfHandleTo<T>::Handle
188 {
189  return typename SdfHandleTo<T>::Handle(p ? *p : T());
190 }
191 
192 template <>
195 
196 template <typename T>
197 typename SdfHandleTo<T>::Handle
199 {
200  return SdfCreateHandle(const_cast<T *>(p));
201 }
202 
204  template<class DST, class SRC>
205  static DST CastSpec(const SRC& spec) {
206  return DST(spec);
207  }
208 };
209 
210 SDF_API bool
212  const SdfSpec& srcSpec, const std::type_info& destType);
213 
214 SDF_API bool
216  const SdfSpec& srcSpec, const std::type_info& destType);
217 
218 template <class DST, class SRC>
220  : std::integral_constant<bool,
221  std::is_base_of<DST, SRC>::value ||
222  std::is_base_of<SRC, DST>::value>
223 { };
224 
225 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
226 /// behaves similar to a dynamic_cast. If class DST cannot represent
227 /// the spec pointed to be \p x, or if the classes DST and SRC are
228 /// not directly related to each other in the C++ type hierarchy,
229 /// the conversion fails and an invalid handle is returned.
230 ///
231 /// XXX: The second condition in the above statement is currently untrue.
232 /// This function will allow casting between spec classes even if
233 /// they are not directly related. Doing so could lead to schema
234 /// mismatches and other buggy behavior.
235 template <typename DST, typename SRC>
236 inline
239 {
240  typedef typename DST::SpecType Spec;
241  typedef SdfHandle<Spec> Handle;
242 
243  if (Sdf_CanCastToType(x.GetSpec(), typeid(Spec))) {
244  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
245  }
246 
247  return Handle();
248 }
249 
250 template <typename DST, typename SRC>
251 inline
254 {
255  return TfDynamic_cast(x);
256 }
257 
258 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
259 /// behaves similar to a static_cast. No runtime checks are performed
260 /// to ensure the conversion is valid; it is up to the consumer to
261 /// ensure this.
262 template <typename DST, typename SRC>
263 inline
266 {
267  typedef typename DST::SpecType Spec;
268  typedef SdfHandle<Spec> Handle;
270  "Spec and SRC must be directly related.");
271 
272  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
273 }
274 
275 template <typename T>
276 inline
279 {
280  return TfStatic_cast<T>(x);
281 }
282 
283 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
284 /// similar to TfDynamic_cast, but it allows the SRC and DST spec to be
285 /// indirectly related, so long as the schema associated with the DST
286 /// spec type is a subclass of the schema associated with \p x.
287 template <typename DST, typename SRC>
288 inline
291 {
292  typedef typename DST::SpecType Spec;
293  typedef SdfHandle<Spec> Handle;
294 
295  if (Sdf_CanCastToTypeCheckSchema(x.GetSpec(), typeid(Spec))) {
296  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
297  }
298 
299  return Handle();
300 }
301 
302 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
303 /// similar to TfStatic_cast, but it allows the SRC and DST spec to be
304 /// indirectly related.
305 template <typename DST, typename SRC>
306 inline
309 {
310  typedef typename DST::SpecType Spec;
311  typedef SdfHandle<Spec> Handle;
312  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
313 }
314 
315 /// Convert SRC_SPEC to a DST_SPEC.
316 template <typename DST_SPEC, typename SRC_SPEC>
317 inline
318 DST_SPEC
319 SdfSpecStatic_cast(const SRC_SPEC& x)
320 {
321  return Sdf_CastAccess::CastSpec<DST_SPEC,SRC_SPEC>(x);
322 }
323 
325 typedef std::vector<TfRefPtr<SdfLayer> > SdfLayerRefPtrVector;
327 
328 #define SDF_DECLARE_HANDLES(cls) \
329  typedef SdfHandleTo<class cls>::Handle cls##Handle; \
330  typedef SdfHandleTo<class cls>::ConstHandle cls##ConstHandle; \
331  typedef SdfHandleTo<class cls>::Vector cls##HandleVector; \
332  typedef SdfHandleTo<class cls>::ConstVector cls##ConstHandleVector
333 
335 
336 #endif // PXR_USD_SDF_DECLARE_HANDLES_H
friend bool operator>=(const SdfHandle &lhs, const SdfHandle &rhs)
type
Definition: core.h:556
SdfHandle(const SpecType &spec)
Definition: layer.h:81
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:32
SdfHandle< T > Handle
std::set< SdfHandleTo< SdfLayer >::Handle > SdfLayerHandleSet
TfWeakPtr< SdfLayer > Handle
SdfHandle< typename DST::SpecType > TfSafeDynamic_cast(const SdfHandle< SRC > &x)
std::vector< ConstHandle > ConstVector
friend bool operator<=(const SdfHandle &lhs, const SdfHandle &rhs)
#define ARCH_UNLIKELY(x)
Definition: hints.h:30
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:23
bool operator!() const
SdfHandleTo< T >::Handle SdfCreateNonConstHandle(T const *p)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
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:74
SdfHandle(TfNullPtrType)
OIIO_UTIL_API const char * c_str(string_view str)
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.
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