4c8b88f2b0956693660d01e488abb93461b6740b
[ardour.git] / libs / pbd / boost-debug / shared_ptr.hpp
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 {};
63 struct polymorphic_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
121     typedef shared_ptr<T> this_type;
122
123 public:
124
125     typedef T element_type;
126     typedef T value_type;
127     typedef T * pointer;
128     typedef typename detail::shared_ptr_traits<T>::reference reference;
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     {
137         detail::sp_enable_shared_from_this( pn, p, p );
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     {
148         detail::sp_enable_shared_from_this( pn, p, p );
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);
212         detail::sp_enable_shared_from_this( pn, tmp, tmp );
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 {
388     return shared_ptr<T>(r, detail::static_cast_tag());
389 }
390
391 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
392 {
393     return shared_ptr<T>(r, detail::const_cast_tag());
394 }
395
396 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
397 {
398     return shared_ptr<T>(r, detail::dynamic_cast_tag());
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 {
405     return shared_ptr<T>(r, detail::static_cast_tag());
406 }
407
408 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
409 {
410     return shared_ptr<T>(r, detail::dynamic_cast_tag());
411 }
412
413 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
414 {
415     return shared_ptr<T>(r, detail::polymorphic_cast_tag());
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