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 SDF_DECLAREHANDLES_H
25 #define SDF_DECLAREHANDLES_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  SpecType _spec;
153 
154  template <class U> friend class SdfHandle;
155 };
156 
157 template <class T>
158 T*
160 {
161  return !x ? 0 : x.operator->();
162 }
163 
165 
166 namespace hboost {
167 
168 using PXR_NS::get_pointer;
169 
170 }
171 
173 
174 template <class T>
175 struct SdfHandleTo {
178  typedef std::vector<Handle> Vector;
179  typedef std::vector<ConstHandle> ConstVector;
180 };
181 
182 template <>
186  typedef std::vector<Handle> Vector;
187  typedef std::vector<ConstHandle> ConstVector;
188 };
189 
190 template <typename T>
191 typename SdfHandleTo<T>::Handle
193 {
194  return typename SdfHandleTo<T>::Handle(p ? *p : T());
195 }
196 
197 template <>
200 
201 template <typename T>
202 typename SdfHandleTo<T>::Handle
204 {
205  return SdfCreateHandle(const_cast<T *>(p));
206 }
207 
209  template<class DST, class SRC>
210  static DST CastSpec(const SRC& spec) {
211  return DST(spec);
212  }
213 };
214 
215 SDF_API bool
217  const SdfSpec& srcSpec, const std::type_info& destType);
218 
219 SDF_API bool
221  const SdfSpec& srcSpec, const std::type_info& destType);
222 
223 template <class DST, class SRC>
225  : std::integral_constant<bool,
226  std::is_base_of<DST, SRC>::value ||
227  std::is_base_of<SRC, DST>::value>
228 { };
229 
230 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
231 /// behaves similar to a dynamic_cast. If class DST cannot represent
232 /// the spec pointed to be \p x, or if the classes DST and SRC are
233 /// not directly related to each other in the C++ type hierarchy,
234 /// the conversion fails and an invalid handle is returned.
235 ///
236 /// XXX: The second condition in the above statement is currently untrue.
237 /// This function will allow casting between spec classes even if
238 /// they are not directly related. Doing so could lead to schema
239 /// mismatches and other buggy behavior.
240 template <typename DST, typename SRC>
241 inline
244 {
245  typedef typename DST::SpecType Spec;
246  typedef SdfHandle<Spec> Handle;
247 
248  if (Sdf_CanCastToType(x.GetSpec(), typeid(Spec))) {
249  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
250  }
251 
252  return Handle();
253 }
254 
255 template <typename DST, typename SRC>
256 inline
259 {
260  return TfDynamic_cast(x);
261 }
262 
263 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function
264 /// behaves similar to a static_cast. No runtime checks are performed
265 /// to ensure the conversion is valid; it is up to the consumer to
266 /// ensure this.
267 template <typename DST, typename SRC>
268 inline
271 {
272  typedef typename DST::SpecType Spec;
273  typedef SdfHandle<Spec> Handle;
275  "Spec and SRC must be directly related.");
276 
277  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
278 }
279 
280 template <typename T>
281 inline
284 {
285  return TfStatic_cast<T>(x);
286 }
287 
288 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
289 /// similar to TfDynamic_cast, but it allows the SRC and DST spec to be
290 /// indirectly related, so long as the schema associated with the DST
291 /// spec type is a subclass of the schema associated with \p x.
292 template <typename DST, typename SRC>
293 inline
296 {
297  typedef typename DST::SpecType Spec;
298  typedef SdfHandle<Spec> Handle;
299 
300  if (Sdf_CanCastToTypeCheckSchema(x.GetSpec(), typeid(Spec))) {
301  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
302  }
303 
304  return Handle();
305 }
306 
307 /// Convert SdfHandle<SRC> \p x to an SdfHandle<DST>. This function is
308 /// similar to TfStatic_cast, but it allows the SRC and DST spec to be
309 /// indirectly related.
310 template <typename DST, typename SRC>
311 inline
314 {
315  typedef typename DST::SpecType Spec;
316  typedef SdfHandle<Spec> Handle;
317  return Handle(Sdf_CastAccess::CastSpec<Spec,SRC>(x.GetSpec()));
318 }
319 
320 /// Convert SRC_SPEC to a DST_SPEC.
321 template <typename DST_SPEC, typename SRC_SPEC>
322 inline
323 DST_SPEC
324 SdfSpecStatic_cast(const SRC_SPEC& x)
325 {
326  return Sdf_CastAccess::CastSpec<DST_SPEC,SRC_SPEC>(x);
327 }
328 
330 typedef std::vector<TfRefPtr<SdfLayer> > SdfLayerRefPtrVector;
332 
333 #define SDF_DECLARE_HANDLES(cls) \
334  typedef SdfHandleTo<class cls>::Handle cls##Handle; \
335  typedef SdfHandleTo<class cls>::ConstHandle cls##ConstHandle; \
336  typedef SdfHandleTo<class cls>::Vector cls##HandleVector; \
337  typedef SdfHandleTo<class cls>::ConstVector cls##ConstHandleVector
338 
340 
341 #endif // SDF_DECLAREHANDLES_H
SdfHandle(const SpecType &spec)
Definition: layer.h:93
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:51
SdfHandle< T > Handle
T * get_pointer(const SdfHandle< T > &x)
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)
std::vector< ConstHandle > ConstVector
Definition: hash.h:44
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
std::vector< Handle > Vector
GLint GLint GLint GLint GLint x
Definition: glew.h:1252
std::vector< TfRefPtr< SdfLayer > > SdfLayerRefPtrVector
SdfHandle< typename DST::SpecType > TfDynamic_cast(const SdfHandle< SRC > &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
SDF_API bool Sdf_CanCastToType(const SdfSpec &srcSpec, const std::type_info &destType)
SdfHandle(const SdfHandle< U > &x)
GLfloat GLfloat p
Definition: glew.h:16321
#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:1245
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:83
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.
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)
type
Definition: core.h:528
void * Handle
Definition: plugin.h:53