fixing stuff
[dyninst.git] / dynutil / h / dyn_detail / boost / shared_ptr.hpp
1 #ifndef DYN_DETAIL_BOOST_SHARED_PTR_HPP_INCLUDED
2 #define DYN_DETAIL_BOOST_SHARED_PTR_HPP_INCLUDED
3
4 //
5 //  shared_ptr.hpp
6 //
7 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 //  Copyright (c) 2001-2008 Peter Dimov
9 //
10 //  Distributed under the Boost Software License, Version 1.0. (See
11 //  accompanying file LICENSE_1_0.txt or copy at
12 //  http://www.boost.org/LICENSE_1_0.txt)
13 //
14 //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
15 //
16
17 #include <dyn_detail/boost/config.hpp>   // for broken compiler workarounds
18
19 #if defined(DYN_DETAIL_BOOST_NO_MEMBER_TEMPLATES) && !defined(DYN_DETAIL_BOOST_MSVC6_MEMBER_TEMPLATES)
20 #include <dyn_detail/boost/detail/shared_ptr_nmt.hpp>
21 #else
22
23 // In order to avoid circular dependencies with Boost.TR1
24 // we make sure that our include of <memory> doesn't try to
25 // pull in the TR1 headers: that's why we use this header 
26 // rather than including <memory> directly:
27 #include <dyn_detail/boost/config/no_tr1/memory.hpp>  // std::auto_ptr
28
29 #include <dyn_detail/boost/assert.hpp>
30 #include <dyn_detail/boost/checked_delete.hpp>
31 #include <dyn_detail/boost/throw_exception.hpp>
32 #include <dyn_detail/boost/detail/shared_count.hpp>
33 #include <dyn_detail/boost/detail/workaround.hpp>
34 #include <dyn_detail/boost/detail/sp_convertible.hpp>
35
36 #if !defined(DYN_DETAIL_BOOST_SP_NO_ATOMIC_ACCESS)
37 #include <dyn_detail/boost/detail/spinlock_pool.hpp>
38 #include <dyn_detail/boost/memory_order.hpp>
39 #endif
40
41 #include <algorithm>            // for std::swap
42 #include <functional>           // for std::less
43 #include <typeinfo>             // for std::bad_cast
44
45 #if !defined(DYN_DETAIL_BOOST_NO_IOSTREAM)
46 #if !defined(DYN_DETAIL_BOOST_NO_IOSFWD)
47 #include <iosfwd>               // for std::basic_ostream
48 #else
49 #include <ostream>
50 #endif
51 #endif
52
53 #ifdef DYN_DETAIL_BOOST_MSVC  // moved here to work around VC++ compiler crash
54 # pragma warning(push)
55 # pragma warning(disable:4284) // odd return type for operator->
56 #endif
57
58 namespace dyn_detail
59 {
60   
61 namespace boost
62 {
63
64 template<class T> class weak_ptr;
65 template<class T> class enable_shared_from_this;
66
67 namespace detail
68 {
69
70 struct static_cast_tag {};
71 struct const_cast_tag {};
72 struct dynamic_cast_tag {};
73 struct polymorphic_cast_tag {};
74
75 template<class T> struct shared_ptr_traits
76 {
77     typedef T & reference;
78 };
79
80 template<> struct shared_ptr_traits<void>
81 {
82     typedef void reference;
83 };
84
85 #if !defined(DYN_DETAIL_BOOST_NO_CV_VOID_SPECIALIZATIONS)
86
87 template<> struct shared_ptr_traits<void const>
88 {
89     typedef void reference;
90 };
91
92 template<> struct shared_ptr_traits<void volatile>
93 {
94     typedef void reference;
95 };
96
97 template<> struct shared_ptr_traits<void const volatile>
98 {
99     typedef void reference;
100 };
101
102 #endif
103
104 // enable_shared_from_this support
105
106 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 )
107 {
108     if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
109 }
110
111 #ifdef _MANAGED
112
113 // Avoid C4793, ... causes native code generation
114
115 struct sp_any_pointer
116 {
117     template<class T> sp_any_pointer( T* ) {}
118 };
119
120 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )
121 {
122 }
123
124 #else // _MANAGED
125
126 #ifdef sgi
127 // Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed
128 # pragma set woff 3506
129 #endif
130
131 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
132 {
133 }
134
135 #ifdef sgi
136 # pragma reset woff 3506
137 #endif
138
139 #endif // _MANAGED
140
141 #if !defined( DYN_DETAIL_BOOST_NO_SFINAE ) && !defined( DYN_DETAIL_BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( DYN_DETAIL_BOOST_NO_AUTO_PTR )
142
143 // rvalue auto_ptr support based on a technique by Dave Abrahams
144
145 template< class T, class R > struct sp_enable_if_auto_ptr
146 {
147 };
148
149 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
150 {
151     typedef R type;
152 }; 
153
154 #endif
155
156 } // namespace detail
157
158
159 //
160 //  shared_ptr
161 //
162 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
163 //  The object pointed to is deleted when the last shared_ptr pointing to it
164 //  is destroyed or reset.
165 //
166
167 template<class T> class shared_ptr
168 {
169 private:
170
171     // Borland 5.5.1 specific workaround
172     typedef shared_ptr<T> this_type;
173
174 public:
175
176     typedef T element_type;
177     typedef T value_type;
178     typedef T * pointer;
179     typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
180
181     shared_ptr(): px(0), pn() // never throws in 1.30+
182     {
183     }
184
185     template<class Y>
186     explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
187     {
188         boost::detail::sp_enable_shared_from_this( pn, p, p );
189     }
190
191     //
192     // Requirements: D's copy constructor must not throw
193     //
194     // shared_ptr will release p by calling d(p)
195     //
196
197     template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
198     {
199         boost::detail::sp_enable_shared_from_this( pn, p, p );
200     }
201
202     // As above, but with allocator. A's copy constructor shall not throw.
203
204     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
205     {
206         boost::detail::sp_enable_shared_from_this( pn, p, p );
207     }
208
209 //  generated copy constructor, assignment, destructor are fine...
210
211 //  except that Borland C++ has a bug, and g++ with -Wsynth warns
212 #if defined(__BORLANDC__) || defined(__GNUC__)
213
214     shared_ptr & operator=(shared_ptr const & r) // never throws
215     {
216         px = r.px;
217         pn = r.pn; // shared_count::op= doesn't throw
218         return *this;
219     }
220
221 #endif
222
223     template<class Y>
224     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
225     {
226         // it is now safe to copy r.px, as pn(r.pn) did not throw
227         px = r.px;
228     }
229
230     template<class Y>
231     shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws
232     {
233         if( !pn.empty() )
234         {
235             px = r.px;
236         }
237     }
238
239     template<class Y>
240 #if !defined( DYN_DETAIL_BOOST_SP_NO_SP_CONVERTIBLE )
241
242     shared_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
243
244 #else
245
246     shared_ptr( shared_ptr<Y> const & r )
247
248 #endif
249     : px( r.px ), pn( r.pn ) // never throws
250     {
251     }
252
253     // aliasing
254     template< class Y >
255     shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
256     {
257     }
258
259     template<class Y>
260     shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
261     {
262     }
263
264     template<class Y>
265     shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
266     {
267     }
268
269     template<class Y>
270     shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
271     {
272         if(px == 0) // need to allocate new counter -- the cast failed
273         {
274             pn = boost::detail::shared_count();
275         }
276     }
277
278     template<class Y>
279     shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
280     {
281         if(px == 0)
282         {
283             boost::throw_exception(std::bad_cast());
284         }
285     }
286
287 #ifndef DYN_DETAIL_BOOST_NO_AUTO_PTR
288
289     template<class Y>
290     explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
291     {
292         Y * tmp = r.get();
293         pn = boost::detail::shared_count(r);
294         boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
295     }
296
297 #if !defined( DYN_DETAIL_BOOST_NO_SFINAE ) && !defined( DYN_DETAIL_BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
298
299     template<class Ap>
300     shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
301     {
302         typename Ap::element_type * tmp = r.get();
303         pn = boost::detail::shared_count( r );
304         boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
305     }
306
307
308 #endif // DYN_DETAIL_BOOST_NO_SFINAE, DYN_DETAIL_BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
309
310 #endif // DYN_DETAIL_BOOST_NO_AUTO_PTR
311
312 #if !defined(DYN_DETAIL_BOOST_MSVC) || (DYN_DETAIL_BOOST_MSVC >= 1300)
313
314     template<class Y>
315     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
316     {
317         px = r.px;
318         pn = r.pn; // shared_count::op= doesn't throw
319         return *this;
320     }
321
322 #endif
323
324 #ifndef DYN_DETAIL_BOOST_NO_AUTO_PTR
325
326     template<class Y>
327     shared_ptr & operator=( std::auto_ptr<Y> & r )
328     {
329         this_type(r).swap(*this);
330         return *this;
331     }
332
333 #if !defined( DYN_DETAIL_BOOST_NO_SFINAE ) && !defined( DYN_DETAIL_BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
334
335     template<class Ap>
336     typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
337     {
338         this_type( r ).swap( *this );
339         return *this;
340     }
341
342
343 #endif // DYN_DETAIL_BOOST_NO_SFINAE, DYN_DETAIL_BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
344
345 #endif // DYN_DETAIL_BOOST_NO_AUTO_PTR
346
347 // Move support
348
349 #if defined( DYN_DETAIL_BOOST_HAS_RVALUE_REFS )
350
351     shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
352     {
353         pn.swap( r.pn );
354         r.px = 0;
355     }
356
357     template<class Y>
358 #if !defined( DYN_DETAIL_BOOST_SP_NO_SP_CONVERTIBLE )
359
360     shared_ptr( shared_ptr<Y> && r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
361
362 #else
363
364     shared_ptr( shared_ptr<Y> && r )
365
366 #endif
367     : px( r.px ), pn() // never throws
368     {
369         pn.swap( r.pn );
370         r.px = 0;
371     }
372
373     shared_ptr & operator=( shared_ptr && r ) // never throws
374     {
375         this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
376         return *this;
377     }
378
379     template<class Y>
380     shared_ptr & operator=( shared_ptr<Y> && r ) // never throws
381     {
382         this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
383         return *this;
384     }
385
386 #endif
387
388     void reset() // never throws in 1.30+
389     {
390         this_type().swap(*this);
391     }
392
393     template<class Y> void reset(Y * p) // Y must be complete
394     {
395         DYN_DETAIL_BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
396         this_type(p).swap(*this);
397     }
398
399     template<class Y, class D> void reset( Y * p, D d )
400     {
401         this_type( p, d ).swap( *this );
402     }
403
404     template<class Y, class D, class A> void reset( Y * p, D d, A a )
405     {
406         this_type( p, d, a ).swap( *this );
407     }
408
409     template<class Y> void reset( shared_ptr<Y> const & r, T * p )
410     {
411         this_type( r, p ).swap( *this );
412     }
413
414     reference operator* () const // never throws
415     {
416         DYN_DETAIL_BOOST_ASSERT(px != 0);
417         return *px;
418     }
419
420     T * operator-> () const // never throws
421     {
422         DYN_DETAIL_BOOST_ASSERT(px != 0);
423         return px;
424     }
425
426     T * get() const // never throws
427     {
428         return px;
429     }
430
431     // implicit conversion to "bool"
432
433 #if ( defined(__SUNPRO_CC) && DYN_DETAIL_BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
434
435     operator bool () const
436     {
437         return px != 0;
438     }
439
440 #elif defined( _MANAGED )
441
442     static void unspecified_bool( this_type*** )
443     {
444     }
445
446     typedef void (*unspecified_bool_type)( this_type*** );
447
448     operator unspecified_bool_type() const // never throws
449     {
450         return px == 0? 0: unspecified_bool;
451     }
452
453 #elif \
454     ( defined(__MWERKS__) && DYN_DETAIL_BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
455     ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
456     ( defined(__SUNPRO_CC) && DYN_DETAIL_BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
457
458     typedef T * (this_type::*unspecified_bool_type)() const;
459
460     operator unspecified_bool_type() const // never throws
461     {
462         return px == 0? 0: &this_type::get;
463     }
464
465 #else
466
467     typedef T * this_type::*unspecified_bool_type;
468
469     operator unspecified_bool_type() const // never throws
470     {
471         return px == 0? 0: &this_type::px;
472     }
473
474 #endif
475
476     // operator! is redundant, but some compilers need it
477
478     bool operator! () const // never throws
479     {
480         return px == 0;
481     }
482
483     bool unique() const // never throws
484     {
485         return pn.unique();
486     }
487
488     long use_count() const // never throws
489     {
490         return pn.use_count();
491     }
492
493     void swap(shared_ptr<T> & other) // never throws
494     {
495         std::swap(px, other.px);
496         pn.swap(other.pn);
497     }
498
499     template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
500     {
501         return pn < rhs.pn;
502     }
503
504     void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
505     {
506         return pn.get_deleter( ti );
507     }
508
509     bool _internal_equiv( shared_ptr const & r ) const
510     {
511         return px == r.px && pn == r.pn;
512     }
513
514 // Tasteless as this may seem, making all members public allows member templates
515 // to work in the absence of member template friends. (Matthew Langston)
516
517 #ifndef DYN_DETAIL_BOOST_NO_MEMBER_TEMPLATE_FRIENDS
518
519 private:
520
521     template<class Y> friend class shared_ptr;
522     template<class Y> friend class weak_ptr;
523
524
525 #endif
526
527     T * px;                     // contained pointer
528     boost::detail::shared_count pn;    // reference counter
529
530 };  // shared_ptr
531
532 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
533 {
534     return a.get() == b.get();
535 }
536
537 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
538 {
539     return a.get() != b.get();
540 }
541
542 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
543
544 // Resolve the ambiguity between our op!= and the one in rel_ops
545
546 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
547 {
548     return a.get() != b.get();
549 }
550
551 #endif
552
553 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
554 {
555     return a._internal_less(b);
556 }
557
558 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
559 {
560     a.swap(b);
561 }
562
563 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
564 {
565     return shared_ptr<T>(r, boost::detail::static_cast_tag());
566 }
567
568 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
569 {
570     return shared_ptr<T>(r, boost::detail::const_cast_tag());
571 }
572
573 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
574 {
575     return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
576 }
577
578 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
579
580 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
581 {
582     return shared_ptr<T>(r, boost::detail::static_cast_tag());
583 }
584
585 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
586 {
587     return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
588 }
589
590 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
591 {
592     return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
593 }
594
595 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
596 {
597     DYN_DETAIL_BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
598     return shared_static_cast<T>(r);
599 }
600
601 // get_pointer() enables boost::mem_fn to recognize shared_ptr
602
603 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
604 {
605     return p.get();
606 }
607
608 // operator<<
609
610 #if !defined(DYN_DETAIL_BOOST_NO_IOSTREAM)
611
612 #if defined(DYN_DETAIL_BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )
613
614 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
615 {
616     os << p.get();
617     return os;
618 }
619
620 #else
621
622 // in STLport's no-iostreams mode no iostream symbols can be used
623 #ifndef _STLP_NO_IOSTREAMS
624
625 # if defined(DYN_DETAIL_BOOST_MSVC) && DYN_DETAIL_BOOST_WORKAROUND(DYN_DETAIL_BOOST_MSVC, < 1300 && __SGI_STL_PORT)
626 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
627 using std::basic_ostream;
628 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
629 # else
630 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
631 # endif
632 {
633     os << p.get();
634     return os;
635 }
636
637 #endif // _STLP_NO_IOSTREAMS
638
639 #endif // __GNUC__ < 3
640
641 #endif // !defined(DYN_DETAIL_BOOST_NO_IOSTREAM)
642
643 // get_deleter
644
645 #if ( defined(__GNUC__) && DYN_DETAIL_BOOST_WORKAROUND(__GNUC__, < 3) ) || \
646     ( defined(__EDG_VERSION__) && DYN_DETAIL_BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
647     ( defined(__HP_aCC) && DYN_DETAIL_BOOST_WORKAROUND(__HP_aCC, <= 33500) )
648
649 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
650 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
651
652 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
653 {
654     void const * q = p._internal_get_deleter(DYN_DETAIL_BOOST_SP_TYPEID(D));
655     return const_cast<D *>(static_cast<D const *>(q));
656 }
657
658 #else
659
660 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
661 {
662     return static_cast<D *>(p._internal_get_deleter(DYN_DETAIL_BOOST_SP_TYPEID(D)));
663 }
664
665 #endif
666
667 // atomic access
668
669 #if !defined(DYN_DETAIL_BOOST_SP_NO_ATOMIC_ACCESS)
670
671 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )
672 {
673     return false;
674 }
675
676 template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
677 {
678     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
679     return *p;
680 }
681
682 template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )
683 {
684     return atomic_load( p );
685 }
686
687 template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
688 {
689     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
690     p->swap( r );
691 }
692
693 template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
694 {
695     atomic_store( p, r ); // std::move( r )
696 }
697
698 template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
699 {
700     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
701
702     sp.lock();
703     p->swap( r );
704     sp.unlock();
705
706     return r; // return std::move( r )
707 }
708
709 template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
710 {
711     return atomic_exchange( p, r ); // std::move( r )
712 }
713
714 template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
715 {
716     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
717
718     sp.lock();
719
720     if( p->_internal_equiv( *v ) )
721     {
722         p->swap( w );
723
724         sp.unlock();
725
726         return true;
727     }
728     else
729     {
730         shared_ptr<T> tmp( *p );
731
732         sp.unlock();
733
734         tmp.swap( *v );
735         return false;
736     }
737 }
738
739 template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order /*success*/, memory_order /*failure*/ )
740 {
741     return atomic_compare_exchange( p, v, w ); // std::move( w )
742 }
743
744 #endif
745
746 } // namespace boost
747 } // namespace dyn_detail
748
749 #ifdef DYN_DETAIL_BOOST_MSVC
750 # pragma warning(pop)
751 #endif
752
753 #endif  // #if defined(DYN_DETAIL_BOOST_NO_MEMBER_TEMPLATES) && !defined(DYN_DETAIL_BOOST_MSVC6_MEMBER_TEMPLATES)
754
755 #endif  // #ifndef DYN_DETAIL_BOOST_SHARED_PTR_HPP_INCLUDED