ardour
shared_ptr.hpp
Go to the documentation of this file.
1 #define DEBUG_SHARED_PTR
2 #ifndef DEBUG_SHARED_PTR
3 
4 #include <boost/shared_ptr.hpp>
5 
6 #else
7 
8 #include "pbd/stacktrace.h"
9 
10 #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
11 #define BOOST_SHARED_PTR_HPP_INCLUDED
12 
13 //
14 // shared_ptr.hpp
15 //
16 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
17 // Copyright (c) 2001, 2002, 2003 Peter Dimov
18 //
19 // Distributed under the Boost Software License, Version 1.0. (See
20 // accompanying file LICENSE_1_0.txt or copy at
21 // http://www.boost.org/LICENSE_1_0.txt)
22 //
23 // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
24 //
25 
26 #include "pbd/stacktrace.h"
27 
28 #include <boost/config.hpp> // for broken compiler workarounds
29 
30 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
31 #include <boost/detail/shared_ptr_nmt.hpp>
32 #else
33 
34 #include <boost/assert.hpp>
35 #include <boost/checked_delete.hpp>
36 #include <boost/throw_exception.hpp>
37 #include <boost/detail/shared_count.hpp>
38 #include <boost/detail/workaround.hpp>
39 
40 #include <memory> // for std::auto_ptr
41 #include <algorithm> // for std::swap
42 #include <functional> // for std::less
43 #include <typeinfo> // for std::bad_cast
44 #include <iosfwd> // for std::basic_ostream
45 
46 #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
47 # pragma warning(push)
48 # pragma warning(disable:4284) // odd return type for operator->
49 #endif
50 
51 namespace boost
52 {
53 
54 template<class T> class weak_ptr;
55 template<class T> class enable_shared_from_this;
56 
57 namespace detail
58 {
59 
60 struct static_cast_tag {};
61 struct const_cast_tag {};
62 struct dynamic_cast_tag {};
64 
65 template<class T> struct shared_ptr_traits
66 {
67  typedef T & reference;
68 };
69 
70 template<> struct shared_ptr_traits<void>
71 {
72  typedef void reference;
73 };
74 
75 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
76 
77 template<> struct shared_ptr_traits<void const>
78 {
79  typedef void reference;
80 };
81 
82 template<> struct shared_ptr_traits<void volatile>
83 {
84  typedef void reference;
85 };
86 
87 template<> struct shared_ptr_traits<void const volatile>
88 {
89  typedef void reference;
90 };
91 
92 #endif
93 
94 // enable_shared_from_this support
95 
96 template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px )
97 {
98  if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
99 }
100 
101 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
102 {
103 }
104 
105 } // namespace detail
106 
107 
108 //
109 // shared_ptr
110 //
111 // An enhanced relative of scoped_ptr with reference counted copy semantics.
112 // The object pointed to is deleted when the last shared_ptr pointing to it
113 // is destroyed or reset.
114 //
115 
116 template<class T> class shared_ptr
117 {
118 private:
119 
120  // Borland 5.5.1 specific workaround
122 
123 public:
124 
125  typedef T element_type;
126  typedef T value_type;
127  typedef T * pointer;
129 
130  shared_ptr(): px(0), pn() // never throws in 1.30+
131  {
132  }
133 
134  template<class Y>
135  explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
136  {
138  }
139 
140  //
141  // Requirements: D's copy constructor must not throw
142  //
143  // shared_ptr will release p by calling d(p)
144  //
145 
146  template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
147  {
149  }
150 
151 // generated copy constructor, assignment, destructor are fine...
152 
153 // except that Borland C++ has a bug, and g++ with -Wsynth warns
154 #if defined(__BORLANDC__) || defined(__GNUC__)
155 
156  shared_ptr & operator=(shared_ptr const & r) // never throws
157  {
158  px = r.px;
159  pn = r.pn; // shared_count::op= doesn't throw
160  return *this;
161  }
162 
163 #endif
164 
165  template<class Y>
166  explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
167  {
168  // it is now safe to copy r.px, as pn(r.pn) did not throw
169  px = r.px;
170  }
171 
172  template<class Y>
173  shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
174  {
175  }
176 
177  template<class Y>
178  shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
179  {
180  }
181 
182  template<class Y>
183  shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
184  {
185  }
186 
187  template<class Y>
188  shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
189  {
190  if(px == 0) // need to allocate new counter -- the cast failed
191  {
192  pn = detail::shared_count();
193  }
194  }
195 
196  template<class Y>
197  shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
198  {
199  if(px == 0)
200  {
201  boost::throw_exception(std::bad_cast());
202  }
203  }
204 
205 #ifndef BOOST_NO_AUTO_PTR
206 
207  template<class Y>
208  explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
209  {
210  Y * tmp = r.get();
211  pn = detail::shared_count(r);
213  }
214 
215 #endif
216 
217 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
218 
219  template<class Y>
220  shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
221  {
222  px = r.px;
223  pn = r.pn; // shared_count::op= doesn't throw
224  return *this;
225  }
226 
227 #endif
228 
229 #ifndef BOOST_NO_AUTO_PTR
230 
231  template<class Y>
232  shared_ptr & operator=(std::auto_ptr<Y> & r)
233  {
234  this_type(r).swap(*this);
235  return *this;
236  }
237 
238 #endif
239 
240  void reset() // never throws in 1.30+
241  {
242  this_type().swap(*this);
243  }
244 
245  template<class Y> void reset(Y * p) // Y must be complete
246  {
247  BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
248  this_type(p).swap(*this);
249  }
250 
251  template<class Y, class D> void reset(Y * p, D d)
252  {
253  this_type(p, d).swap(*this);
254  }
255 
256  reference operator* () const // never throws
257  {
258  BOOST_ASSERT(px != 0);
259  return *px;
260  }
261 
262  T * operator-> () const // never throws
263  {
264  BOOST_ASSERT(px != 0);
265  return px;
266  }
267 
268  T * get() const // never throws
269  {
270  return px;
271  }
272 
273  // implicit conversion to "bool"
274 
275 #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
276 
277  operator bool () const
278  {
279  return px != 0;
280  }
281 
282 #elif \
283  ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
284  ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) )
285 
286  typedef T * (this_type::*unspecified_bool_type)() const;
287 
288  operator unspecified_bool_type() const // never throws
289  {
290  return px == 0? 0: &this_type::get;
291  }
292 
293 #else
294 
295  typedef T * this_type::*unspecified_bool_type;
296 
297  operator unspecified_bool_type() const // never throws
298  {
299  return px == 0? 0: &this_type::px;
300  }
301 
302 #endif
303 
304  // operator! is redundant, but some compilers need it
305 
306  bool operator! () const // never throws
307  {
308  return px == 0;
309  }
310 
311  bool unique() const // never throws
312  {
313  return pn.unique();
314  }
315 
316  long use_count() const // never throws
317  {
318  return pn.use_count();
319  }
320 
321  void swap(shared_ptr<T> & other) // never throws
322  {
323  std::swap(px, other.px);
324  pn.swap(other.pn);
325  }
326 
327  template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
328  {
329  return pn < rhs.pn;
330  }
331 
332  void * _internal_get_deleter(std::type_info const & ti) const
333  {
334  return pn.get_deleter(ti);
335  }
336 
337 // Tasteless as this may seem, making all members public allows member templates
338 // to work in the absence of member template friends. (Matthew Langston)
339 
340 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
341 
342 private:
343 
344  template<class Y> friend class shared_ptr;
345  template<class Y> friend class weak_ptr;
346 
347 #endif
348 
349  T * px; // contained pointer
350  detail::shared_count pn; // reference counter
351  typename PBD::thing_with_backtrace<T> bt; // backtrace
352 
353 }; // shared_ptr
354 
355 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
356 {
357  return a.get() == b.get();
358 }
359 
360 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
361 {
362  return a.get() != b.get();
363 }
364 
365 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
366 
367 // Resolve the ambiguity between our op!= and the one in rel_ops
368 
369 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
370 {
371  return a.get() != b.get();
372 }
373 
374 #endif
375 
376 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
377 {
378  return a._internal_less(b);
379 }
380 
381 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
382 {
383  a.swap(b);
384 }
385 
386 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
387 {
389 }
390 
391 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
392 {
394 }
395 
396 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
397 {
399 }
400 
401 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
402 
403 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
404 {
406 }
407 
408 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
409 {
411 }
412 
413 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
414 {
416 }
417 
418 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
419 {
420  BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
421  return shared_static_cast<T>(r);
422 }
423 
424 // get_pointer() enables boost::mem_fn to recognize shared_ptr
425 
426 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
427 {
428  return p.get();
429 }
430 
431 // operator<<
432 
433 #if defined(__GNUC__) && (__GNUC__ < 3)
434 
435 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
436 {
437  os << p.get();
438  return os;
439 }
440 
441 #else
442 
443 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
444 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
445 using std::basic_ostream;
446 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
447 # else
448 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
449 # endif
450 {
451  os << p.get();
452  return os;
453 }
454 
455 #endif
456 
457 // get_deleter (experimental)
458 
459 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
460  ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
461  ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
462 
463 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
464 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
465 
466 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
467 {
468  void const * q = p._internal_get_deleter(typeid(D));
469  return const_cast<D *>(static_cast<D const *>(q));
470 }
471 
472 #else
473 
474 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
475 {
476  return static_cast<D *>(p._internal_get_deleter(typeid(D)));
477 }
478 
479 #endif
480 
481 } // namespace boost
482 
483 #ifdef BOOST_MSVC
484 # pragma warning(pop)
485 #endif
486 
487 #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
488 
489 #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
490 
491 #endif // #ifndef DEBUG_SHARED_PTR
shared_ptr(shared_ptr< Y > const &r)
Definition: shared_ptr.hpp:173
shared_ptr< T > shared_dynamic_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:408
bool _internal_less(shared_ptr< Y > const &rhs) const
Definition: shared_ptr.hpp:327
bool operator!=(shared_ptr< T > const &a, shared_ptr< U > const &b)
Definition: shared_ptr.hpp:360
detail::shared_ptr_traits< T >::reference reference
Definition: shared_ptr.hpp:128
shared_ptr< T > this_type
Definition: shared_ptr.hpp:121
shared_ptr(shared_ptr< Y > const &r, detail::dynamic_cast_tag)
Definition: shared_ptr.hpp:188
void * _internal_get_deleter(std::type_info const &ti) const
Definition: shared_ptr.hpp:332
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
shared_ptr< T > const_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:391
shared_ptr(Y *p, D d)
Definition: shared_ptr.hpp:146
reference operator*() const
Definition: shared_ptr.hpp:256
void reset(Y *p)
Definition: shared_ptr.hpp:245
shared_ptr(shared_ptr< Y > const &r, detail::static_cast_tag)
Definition: shared_ptr.hpp:178
void reset(Y *p, D d)
Definition: shared_ptr.hpp:251
shared_ptr(shared_ptr< Y > const &r, detail::const_cast_tag)
Definition: shared_ptr.hpp:183
void sp_enable_shared_from_this(shared_count const &pn, boost::enable_shared_from_this< T > const *pe, Y const *px)
Definition: shared_ptr.hpp:96
detail::shared_count pn
Definition: shared_ptr.hpp:350
void swap(shared_ptr< T > &a, shared_ptr< T > &b)
Definition: shared_ptr.hpp:381
shared_ptr(weak_ptr< Y > const &r)
Definition: shared_ptr.hpp:166
shared_ptr< T > shared_static_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:403
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:386
T * get() const
Definition: shared_ptr.hpp:268
bool operator!() const
Definition: shared_ptr.hpp:306
shared_ptr< T > shared_polymorphic_downcast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:418
shared_ptr & operator=(std::auto_ptr< Y > &r)
Definition: shared_ptr.hpp:232
shared_ptr(std::auto_ptr< Y > &r)
Definition: shared_ptr.hpp:208
PBD::thing_with_backtrace< T > bt
Definition: shared_ptr.hpp:351
shared_ptr & operator=(shared_ptr< Y > const &r)
Definition: shared_ptr.hpp:220
void swap(shared_ptr< T > &other)
Definition: shared_ptr.hpp:321
T *this_type::* unspecified_bool_type
Definition: shared_ptr.hpp:295
T * get_pointer(shared_ptr< T > const &p)
Definition: shared_ptr.hpp:426
shared_ptr(shared_ptr< Y > const &r, detail::polymorphic_cast_tag)
Definition: shared_ptr.hpp:197
shared_ptr< T > shared_polymorphic_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:413
T * operator->() const
Definition: shared_ptr.hpp:262
bool unique() const
Definition: shared_ptr.hpp:311
D * get_deleter(shared_ptr< T > const &p)
Definition: shared_ptr.hpp:474
long use_count() const
Definition: shared_ptr.hpp:316
bool operator==(shared_ptr< T > const &a, shared_ptr< U > const &b)
Definition: shared_ptr.hpp:355