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 #include <hboost/operators.hpp>
43 
45 
46 class SdfLayer;
47 class SdfSpec;
48 template <class T> class TfRefPtr;
50 
51 // Sdf_Identities are held via intrusive_ptr so that we can carefully
52 // manage the ref-count to avoid race conditions -- see
53 // Sdf_IdentityRegistry::Identify().
54 typedef hboost::intrusive_ptr<Sdf_Identity> Sdf_IdentityRefPtr;
55 
56 /// \class SdfHandle
57 ///
58 /// SdfHandle is a smart ptr that calls IsDormant() on the pointed-to
59 /// object as an extra expiration check so that dormant objects appear to
60 /// be expired.
61 ///
62 template <class T>
63 class SdfHandle : private hboost::totally_ordered<SdfHandle<T> > {
64 public:
65  typedef SdfHandle<T> This;
66  typedef T SpecType;
67 
70 
71  SdfHandle() { }
73  explicit SdfHandle(const Sdf_IdentityRefPtr& id) : _spec(id) { }
74  SdfHandle(const SpecType& spec) : _spec(spec) { }
75 
76  template <class U>
77  SdfHandle(const SdfHandle<U>& x) : _spec(x._spec) { }
78 
79  This& operator=(const This& x)
80  {
81  const_cast<NonConstSpecType&>(_spec) = x._spec;
82  return *this;
83  }
84 
85  template <class U>
87  {
88  const_cast<NonConstSpecType&>(_spec) = x._spec;
89  return *this;
90  }
91 
92  /// Dereference. Raises a fatal error if the object is invalid or
93  /// dormant.
95  {
96  if (ARCH_UNLIKELY(_spec.IsDormant())) {
97  TF_FATAL_ERROR("Dereferenced an invalid %s",
98  ArchGetDemangled(typeid(SpecType)).c_str());
99  return 0;
100  }
101  return const_cast<SpecType*>(&_spec);
102  }
103 
104  const SpecType & GetSpec() const
105  {
106  return _spec;
107  }
108 
109  void Reset()
110  {
111  const_cast<SpecType&>(_spec) = SpecType();
112  }
113 
114 #if !defined(doxygen)
116 #endif
117 
118  /// Returns \c true in a boolean context if the object is valid,
119  /// \c false otherwise.
120  operator UnspecifiedBoolType() const
121  {
122  return _spec.IsDormant() ? 0 : &This::_spec;
123  }
124  /// Returns \c false in a boolean context if the object is valid,
125  /// \c true otherwise.
126  bool operator!() const
127  {
128  return _spec.IsDormant();
129  }
130 
131  /// Compares handles for equality.
132  template <class U>
133  bool operator==(const SdfHandle<U>& other) const
134  {
135  return _spec == other._spec;
136  }
137 
138  /// Arranges handles in an arbitrary strict weak ordering. Note that
139  /// this ordering is stable across path changes.
140  template <class U>
141  bool operator<(const SdfHandle<U>& other) const
142  {
143  return _spec < other._spec;
144  }
145 
146  /// Hash.
147  friend size_t hash_value(const This &x) {
148  return hash_value(x._spec);
149  }
150 
151 private:
152  friend
153  inline SpecType *get_pointer(const SdfHandle &x) {
154  return ARCH_UNLIKELY(x._spec.IsDormant()) ?
155  nullptr : const_cast<SpecType*>(&x._spec);
156  }
157 
158  SpecType _spec;
159 
160  template <class U> friend class SdfHandle;
161 };
162 
164 
165 namespace hboost {
166 
167 using PXR_NS::get_pointer;
168 
169 }
170 
172 
173 template <class T>
174 struct SdfHandleTo {
177  typedef std::vector<Handle> Vector;
178  typedef std::vector<ConstHandle> ConstVector;
179 };
180 
181 template <>
185  typedef std::vector<Handle> Vector;
186  typedef std::vector<ConstHandle> ConstVector;
187 };
188 
189 template <typename T>
190 typename SdfHandleTo<T>::Handle
192 {
193  return typename SdfHandleTo<T>::Handle(p ? *p : T());
194 }
195 
196 template <>
199 
200 template <typename T>
201 typename SdfHandleTo<T>::Handle
203 {
204  return SdfCreateHandle(const_cast<T *>(p));
205 }
206 
208  template<class DST, class SRC>
209  static DST CastSpec(const SRC& spec) {
210  return DST(spec);
211  }
212 };
213 
214 SDF_API bool
216  const SdfSpec& srcSpec, const std::type_info& destType);
217 
218 SDF_API bool
220  const SdfSpec& srcSpec, const std::type_info& destType);
221 
222 template <class DST, class SRC>
224  : std::integral_constant<bool,
225  std::is_base_of<DST, SRC>::value ||
226  std::is_base_of<SRC, DST>::value>
227 { };
228 
229 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
230 /// behaves similar to a dynamic_cast. If class DST cannot represent
231 /// the spec pointed to be \p x, or if the classes DST and SRC are
232 /// not directly related to each other in the C++ type hierarchy,
233 /// the conversion fails and an invalid handle is returned.
234 ///
235 /// XXX: The second condition in the above statement is currently untrue.
236 /// This function will allow casting between spec classes even if
237 /// they are not directly related. Doing so could lead to schema
238 /// mismatches and other buggy behavior.
239 template <typename DST, typename SRC>
240 inline
243 {
244  typedef typename DST::SpecType Spec;
245  typedef SdfHandle<Spec> Handle;
246 
247  if (Sdf_CanCastToType(x.GetSpec(), typeid(Spec))) {
248  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
249  }
250 
251  return Handle();
252 }
253 
254 template <typename DST, typename SRC>
255 inline
258 {
259  return TfDynamic_cast(x);
260 }
261 
262 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
263 /// behaves similar to a static_cast. No runtime checks are performed
264 /// to ensure the conversion is valid; it is up to the consumer to
265 /// ensure this.
266 template <typename DST, typename SRC>
267 inline
270 {
271  typedef typename DST::SpecType Spec;
272  typedef SdfHandle<Spec> Handle;
274  "Spec and SRC must be directly related.");
275 
276  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
277 }
278 
279 template <typename T>
280 inline
283 {
284  return TfStatic_cast<T>(x);
285 }
286 
287 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
288 /// similar to TfDynamic_cast, but it allows the SRC and DST spec to be
289 /// indirectly related, so long as the schema associated with the DST
290 /// spec type is a subclass of the schema associated with \p x.
291 template <typename DST, typename SRC>
292 inline
295 {
296  typedef typename DST::SpecType Spec;
297  typedef SdfHandle<Spec> Handle;
298 
299  if (Sdf_CanCastToTypeCheckSchema(x.GetSpec(), typeid(Spec))) {
300  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
301  }
302 
303  return Handle();
304 }
305 
306 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
307 /// similar to TfStatic_cast, but it allows the SRC and DST spec to be
308 /// indirectly related.
309 template <typename DST, typename SRC>
310 inline
313 {
314  typedef typename DST::SpecType Spec;
315  typedef SdfHandle<Spec> Handle;
316  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
317 }
318 
319 /// Convert SRC_SPEC to a DST_SPEC.
320 template <typename DST_SPEC, typename SRC_SPEC>
321 inline
322 DST_SPEC
323 SdfSpecStatic_cast(const SRC_SPEC& x)
324 {
325  return Sdf_CastAccess::CastSpec<DST_SPEC,SRC_SPEC>(x);
326 }
327 
329 typedef std::vector<TfRefPtr<SdfLayer> > SdfLayerRefPtrVector;
331 
332 #define SDF_DECLARE_HANDLES(cls) \
333  typedef SdfHandleTo<class cls>::Handle cls##Handle; \
334  typedef SdfHandleTo<class cls>::ConstHandle cls##ConstHandle; \
335  typedef SdfHandleTo<class cls>::Vector cls##HandleVector; \
336  typedef SdfHandleTo<class cls>::ConstVector cls##ConstHandleVector
337 
339 
340 #endif // PXR_USD_SDF_DECLARE_HANDLES_H
SdfHandle(const SpecType &spec)
Definition: layer.h:94
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
#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
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:1441
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