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