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 
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"
34 #include "pxr/base/tf/weakPtrFacade.h"
35 #include "pxr/base/tf/declarePtrs.h"
36 
37 #include <set>
38 #include <typeinfo>
39 #include <type_traits>
40 #include <vector>
41 #include <boost/intrusive_ptr.hpp>
42 #include <boost/operators.hpp>
43 
44 PXR_NAMESPACE_OPEN_SCOPE
45 
46 class SdfLayer;
47 class SdfSpec;
48 template <class T> class TfRefPtr;
49 class Sdf_Identity;
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 boost::intrusive_ptr<Sdf_Identity> Sdf_IdentityRefPtr;
55 
62 template <class T>
63 class SdfHandle : private boost::totally_ordered<SdfHandle<T> > {
64 public:
65  typedef SdfHandle<T> This;
66  typedef T SpecType;
67 
68  typedef typename std::remove_const<SpecType>::type NonConstSpecType;
70 
71  SdfHandle() { }
72  SdfHandle(TfNullPtrType) { }
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>
86  This& operator=(const SdfHandle<U>& x)
87  {
88  const_cast<NonConstSpecType&>(_spec) = x._spec;
89  return *this;
90  }
91 
94  SpecType* operator->() const
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)
115  typedef SpecType This::*UnspecifiedBoolType;
116 #endif
117 
120  operator UnspecifiedBoolType() const
121  {
122  return _spec.IsDormant() ? 0 : &This::_spec;
123  }
126  bool operator!() const
127  {
128  return _spec.IsDormant();
129  }
130 
132  template <class U>
133  bool operator==(const SdfHandle<U>& other) const
134  {
135  return _spec == other._spec;
136  }
137 
140  template <class U>
141  bool operator<(const SdfHandle<U>& other) const
142  {
143  return _spec < other._spec;
144  }
145 
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 
163 PXR_NAMESPACE_CLOSE_SCOPE
164 
165 namespace boost {
166 
167 using PXR_NS::get_pointer;
168 
169 }
170 
171 PXR_NAMESPACE_OPEN_SCOPE
172 
173 template <class T>
174 struct SdfHandleTo {
175  typedef SdfHandle<T> Handle;
176  typedef SdfHandle<const T> ConstHandle;
177  typedef std::vector<Handle> Vector;
178  typedef std::vector<ConstHandle> ConstVector;
179 };
180 
181 template <>
182 struct SdfHandleTo<SdfLayer> {
183  typedef TfWeakPtr<SdfLayer> Handle;
184  typedef TfWeakPtr<const SdfLayer> ConstHandle;
185  typedef std::vector<Handle> Vector;
186  typedef std::vector<ConstHandle> ConstVector;
187 };
188 
189 template <typename T>
190 typename SdfHandleTo<T>::Handle
191 SdfCreateHandle(T *p)
192 {
193  return typename SdfHandleTo<T>::Handle(p ? *p : T());
194 }
195 
196 template <>
197 SDF_API SdfHandleTo<SdfLayer>::Handle
198 SdfCreateHandle(SdfLayer *p);
199 
200 template <typename T>
201 typename SdfHandleTo<T>::Handle
202 SdfCreateNonConstHandle(T const *p)
203 {
204  return SdfCreateHandle(const_cast<T *>(p));
205 }
206 
207 struct Sdf_CastAccess {
208  template<class DST, class SRC>
209  static DST CastSpec(const SRC& spec) {
210  return DST(spec);
211  }
212 };
213 
214 SDF_API bool
215 Sdf_CanCastToType(
216  const SdfSpec& srcSpec, const std::type_info& destType);
217 
218 SDF_API bool
219 Sdf_CanCastToTypeCheckSchema(
220  const SdfSpec& srcSpec, const std::type_info& destType);
221 
222 template <class DST, class SRC>
223 struct Sdf_SpecTypesAreDirectlyRelated
224  : std::integral_constant<bool,
225  std::is_base_of<DST, SRC>::value ||
226  std::is_base_of<SRC, DST>::value>
227 { };
228 
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 
266 template <typename DST, typename SRC>
267 inline
270 {
271  typedef typename DST::SpecType Spec;
272  typedef SdfHandle<Spec> Handle;
273  static_assert(Sdf_SpecTypesAreDirectlyRelated<Spec, SRC>::value,
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
282 TfConst_cast(const SdfHandle<const typename T::SpecType>& x)
283 {
284  return TfStatic_cast<T>(x);
285 }
286 
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 
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 
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;
330 typedef std::set<SdfHandleTo<SdfLayer>::Handle> SdfLayerHandleSet;
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 
338 PXR_NAMESPACE_CLOSE_SCOPE
339 
340 #endif // PXR_USD_SDF_DECLARE_HANDLES_H
A unit of scene description that you combine with other units of scene description to form a shot...
Definition: layer.h:94
TO TfSafeDynamic_cast(FROM *ptr)
Safely perform a dynamic cast.
bool operator!() const
Returns false in a boolean context if the object is valid, true otherwise.
SdfHandle< typename DST::SpecType > TfStatic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle&lt;SRC&gt; x to an SdfHandle&lt;DST&gt;.
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
Return demangled RTTI-generated type name.
Base class for all Sdf spec classes.
Definition: spec.h:51
SdfHandle is a smart ptr that calls IsDormant() on the pointed-to object as an extra expiration check...
Pointer storage with deletion detection.
Definition: refBase.h:38
SdfHandle< typename DST::SpecType > TfDynamic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle&lt;SRC&gt; x to an SdfHandle&lt;DST&gt;.
SdfHandle< typename DST::SpecType > SdfSpecDynamic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle&lt;SRC&gt; x to an SdfHandle&lt;DST&gt;.
#define TF_FATAL_ERROR(fmt, args)
Issue a fatal error and end the program.
Definition: diagnostic.h:108
SpecType * operator->() const
Dereference.
bool operator==(const SdfHandle< U > &other) const
Compares handles for equality.
Reference-counted smart pointer utility class.
Definition: refBase.h:37
friend size_t hash_value(const This &x)
Hash.
SdfHandle< typename DST::SpecType > SdfSpecStatic_cast(const SdfHandle< SRC > &x)
Convert SdfHandle&lt;SRC&gt; x to an SdfHandle&lt;DST&gt;.