]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_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 | // | |
b32b8144 | 14 | // See http://www.boost.org/libs/smart_ptr/ for documentation. |
7c673cae FG |
15 | // |
16 | ||
17 | #include <boost/config.hpp> // for broken compiler workarounds | |
18 | ||
19 | // In order to avoid circular dependencies with Boost.TR1 | |
20 | // we make sure that our include of <memory> doesn't try to | |
21 | // pull in the TR1 headers: that's why we use this header | |
22 | // rather than including <memory> directly: | |
23 | #include <boost/config/no_tr1/memory.hpp> // std::auto_ptr | |
24 | ||
25 | #include <boost/assert.hpp> | |
26 | #include <boost/checked_delete.hpp> | |
27 | #include <boost/throw_exception.hpp> | |
28 | #include <boost/smart_ptr/detail/shared_count.hpp> | |
29 | #include <boost/detail/workaround.hpp> | |
30 | #include <boost/smart_ptr/detail/sp_convertible.hpp> | |
31 | #include <boost/smart_ptr/detail/sp_nullptr_t.hpp> | |
32 | #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp> | |
b32b8144 | 33 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> |
7c673cae FG |
34 | |
35 | #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) | |
36 | #include <boost/smart_ptr/detail/spinlock_pool.hpp> | |
37 | #endif | |
38 | ||
39 | #include <algorithm> // for std::swap | |
40 | #include <functional> // for std::less | |
41 | #include <typeinfo> // for std::bad_cast | |
42 | #include <cstddef> // for std::size_t | |
43 | ||
44 | #if !defined(BOOST_NO_IOSTREAM) | |
45 | #if !defined(BOOST_NO_IOSFWD) | |
46 | #include <iosfwd> // for std::basic_ostream | |
47 | #else | |
48 | #include <ostream> | |
49 | #endif | |
50 | #endif | |
51 | ||
52 | #if defined( BOOST_SP_DISABLE_DEPRECATED ) | |
53 | #pragma GCC diagnostic push | |
54 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
55 | #endif | |
56 | ||
57 | namespace boost | |
58 | { | |
59 | ||
60 | template<class T> class shared_ptr; | |
61 | template<class T> class weak_ptr; | |
62 | template<class T> class enable_shared_from_this; | |
63 | class enable_shared_from_raw; | |
64 | ||
65 | namespace movelib | |
66 | { | |
67 | ||
68 | template< class T, class D > class unique_ptr; | |
69 | ||
70 | } // namespace movelib | |
71 | ||
72 | namespace detail | |
73 | { | |
74 | ||
75 | // sp_element, element_type | |
76 | ||
77 | template< class T > struct sp_element | |
78 | { | |
79 | typedef T type; | |
80 | }; | |
81 | ||
82 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
83 | ||
84 | template< class T > struct sp_element< T[] > | |
85 | { | |
86 | typedef T type; | |
87 | }; | |
88 | ||
89 | #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) | |
90 | ||
91 | template< class T, std::size_t N > struct sp_element< T[N] > | |
92 | { | |
93 | typedef T type; | |
94 | }; | |
95 | ||
96 | #endif | |
97 | ||
98 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
99 | ||
100 | // sp_dereference, return type of operator* | |
101 | ||
102 | template< class T > struct sp_dereference | |
103 | { | |
104 | typedef T & type; | |
105 | }; | |
106 | ||
107 | template<> struct sp_dereference< void > | |
108 | { | |
109 | typedef void type; | |
110 | }; | |
111 | ||
112 | #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) | |
113 | ||
114 | template<> struct sp_dereference< void const > | |
115 | { | |
116 | typedef void type; | |
117 | }; | |
118 | ||
119 | template<> struct sp_dereference< void volatile > | |
120 | { | |
121 | typedef void type; | |
122 | }; | |
123 | ||
124 | template<> struct sp_dereference< void const volatile > | |
125 | { | |
126 | typedef void type; | |
127 | }; | |
128 | ||
129 | #endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) | |
130 | ||
131 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
132 | ||
133 | template< class T > struct sp_dereference< T[] > | |
134 | { | |
135 | typedef void type; | |
136 | }; | |
137 | ||
138 | #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) | |
139 | ||
140 | template< class T, std::size_t N > struct sp_dereference< T[N] > | |
141 | { | |
142 | typedef void type; | |
143 | }; | |
144 | ||
145 | #endif | |
146 | ||
147 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
148 | ||
149 | // sp_member_access, return type of operator-> | |
150 | ||
151 | template< class T > struct sp_member_access | |
152 | { | |
153 | typedef T * type; | |
154 | }; | |
155 | ||
156 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
157 | ||
158 | template< class T > struct sp_member_access< T[] > | |
159 | { | |
160 | typedef void type; | |
161 | }; | |
162 | ||
163 | #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) | |
164 | ||
165 | template< class T, std::size_t N > struct sp_member_access< T[N] > | |
166 | { | |
167 | typedef void type; | |
168 | }; | |
169 | ||
170 | #endif | |
171 | ||
172 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
173 | ||
174 | // sp_array_access, return type of operator[] | |
175 | ||
176 | template< class T > struct sp_array_access | |
177 | { | |
178 | typedef void type; | |
179 | }; | |
180 | ||
181 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
182 | ||
183 | template< class T > struct sp_array_access< T[] > | |
184 | { | |
185 | typedef T & type; | |
186 | }; | |
187 | ||
188 | #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) | |
189 | ||
190 | template< class T, std::size_t N > struct sp_array_access< T[N] > | |
191 | { | |
192 | typedef T & type; | |
193 | }; | |
194 | ||
195 | #endif | |
196 | ||
197 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
198 | ||
199 | // sp_extent, for operator[] index check | |
200 | ||
201 | template< class T > struct sp_extent | |
202 | { | |
203 | enum _vt { value = 0 }; | |
204 | }; | |
205 | ||
206 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
207 | ||
208 | template< class T, std::size_t N > struct sp_extent< T[N] > | |
209 | { | |
210 | enum _vt { value = N }; | |
211 | }; | |
212 | ||
213 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
214 | ||
215 | // enable_shared_from_this support | |
216 | ||
217 | 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 ) | |
218 | { | |
219 | if( pe != 0 ) | |
220 | { | |
221 | pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); | |
222 | } | |
223 | } | |
224 | ||
225 | template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe ); | |
226 | ||
227 | #ifdef _MANAGED | |
228 | ||
229 | // Avoid C4793, ... causes native code generation | |
230 | ||
231 | struct sp_any_pointer | |
232 | { | |
233 | template<class T> sp_any_pointer( T* ) {} | |
234 | }; | |
235 | ||
236 | inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer ) | |
237 | { | |
238 | } | |
239 | ||
240 | #else // _MANAGED | |
241 | ||
242 | inline void sp_enable_shared_from_this( ... ) | |
243 | { | |
244 | } | |
245 | ||
246 | #endif // _MANAGED | |
247 | ||
248 | #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) | |
249 | ||
250 | // rvalue auto_ptr support based on a technique by Dave Abrahams | |
251 | ||
252 | template< class T, class R > struct sp_enable_if_auto_ptr | |
253 | { | |
254 | }; | |
255 | ||
256 | template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > | |
257 | { | |
258 | typedef R type; | |
259 | }; | |
260 | ||
261 | #endif | |
262 | ||
263 | // sp_assert_convertible | |
264 | ||
b32b8144 | 265 | template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPT |
7c673cae FG |
266 | { |
267 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | |
268 | ||
269 | // static_assert( sp_convertible< Y, T >::value ); | |
270 | typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ]; | |
271 | (void)sizeof( tmp ); | |
272 | ||
273 | #else | |
274 | ||
275 | T* p = static_cast< Y* >( 0 ); | |
276 | (void)p; | |
277 | ||
278 | #endif | |
279 | } | |
280 | ||
281 | // pointer constructor helper | |
282 | ||
283 | template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn ) | |
284 | { | |
285 | boost::detail::shared_count( p ).swap( pn ); | |
286 | boost::detail::sp_enable_shared_from_this( ppx, p, p ); | |
287 | } | |
288 | ||
289 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
290 | ||
291 | template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn ) | |
292 | { | |
293 | sp_assert_convertible< Y[], T[] >(); | |
294 | boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn ); | |
295 | } | |
296 | ||
297 | template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn ) | |
298 | { | |
299 | sp_assert_convertible< Y[N], T[N] >(); | |
300 | boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn ); | |
301 | } | |
302 | ||
303 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
304 | ||
305 | // deleter constructor helper | |
306 | ||
307 | template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p ) | |
308 | { | |
309 | boost::detail::sp_enable_shared_from_this( ppx, p, p ); | |
310 | } | |
311 | ||
312 | #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
313 | ||
314 | template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ ) | |
315 | { | |
316 | sp_assert_convertible< Y[], T[] >(); | |
317 | } | |
318 | ||
319 | template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ ) | |
320 | { | |
321 | sp_assert_convertible< Y[N], T[N] >(); | |
322 | } | |
323 | ||
324 | #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
325 | ||
b32b8144 FG |
326 | struct sp_internal_constructor_tag |
327 | { | |
328 | }; | |
329 | ||
7c673cae FG |
330 | } // namespace detail |
331 | ||
332 | ||
333 | // | |
334 | // shared_ptr | |
335 | // | |
336 | // An enhanced relative of scoped_ptr with reference counted copy semantics. | |
337 | // The object pointed to is deleted when the last shared_ptr pointing to it | |
338 | // is destroyed or reset. | |
339 | // | |
340 | ||
341 | template<class T> class shared_ptr | |
342 | { | |
343 | private: | |
344 | ||
345 | // Borland 5.5.1 specific workaround | |
346 | typedef shared_ptr<T> this_type; | |
347 | ||
348 | public: | |
349 | ||
350 | typedef typename boost::detail::sp_element< T >::type element_type; | |
351 | ||
b32b8144 | 352 | BOOST_CONSTEXPR shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn() |
7c673cae FG |
353 | { |
354 | } | |
355 | ||
356 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
357 | ||
b32b8144 FG |
358 | BOOST_CONSTEXPR shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn() |
359 | { | |
360 | } | |
361 | ||
362 | #endif | |
363 | ||
364 | BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ ) | |
365 | { | |
366 | } | |
367 | ||
368 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
369 | ||
370 | BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( std::move( pn_ ) ) | |
7c673cae FG |
371 | { |
372 | } | |
373 | ||
374 | #endif | |
375 | ||
376 | template<class Y> | |
377 | explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete | |
378 | { | |
379 | boost::detail::sp_pointer_construct( this, p, pn ); | |
380 | } | |
381 | ||
382 | // | |
383 | // Requirements: D's copy constructor must not throw | |
384 | // | |
385 | // shared_ptr will release p by calling d(p) | |
386 | // | |
387 | ||
388 | template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d ) | |
389 | { | |
390 | boost::detail::sp_deleter_construct( this, p ); | |
391 | } | |
392 | ||
393 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
394 | ||
395 | template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d ) | |
396 | { | |
397 | } | |
398 | ||
399 | #endif | |
400 | ||
401 | // As above, but with allocator. A's copy constructor shall not throw. | |
402 | ||
403 | template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) | |
404 | { | |
405 | boost::detail::sp_deleter_construct( this, p ); | |
406 | } | |
407 | ||
408 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
409 | ||
410 | template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a ) | |
411 | { | |
412 | } | |
413 | ||
414 | #endif | |
415 | ||
416 | // generated copy constructor, destructor are fine... | |
417 | ||
418 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
419 | ||
420 | // ... except in C++0x, move disables the implicit copy | |
421 | ||
b32b8144 | 422 | shared_ptr( shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) |
7c673cae FG |
423 | { |
424 | } | |
425 | ||
426 | #endif | |
427 | ||
428 | template<class Y> | |
429 | explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw | |
430 | { | |
431 | boost::detail::sp_assert_convertible< Y, T >(); | |
432 | ||
433 | // it is now safe to copy r.px, as pn(r.pn) did not throw | |
434 | px = r.px; | |
435 | } | |
436 | ||
437 | template<class Y> | |
438 | shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ) | |
b32b8144 | 439 | BOOST_SP_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) |
7c673cae FG |
440 | { |
441 | if( !pn.empty() ) | |
442 | { | |
443 | px = r.px; | |
444 | } | |
445 | } | |
446 | ||
447 | template<class Y> | |
448 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | |
449 | ||
450 | shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) | |
451 | ||
452 | #else | |
453 | ||
454 | shared_ptr( shared_ptr<Y> const & r ) | |
455 | ||
456 | #endif | |
b32b8144 | 457 | BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) |
7c673cae FG |
458 | { |
459 | boost::detail::sp_assert_convertible< Y, T >(); | |
460 | } | |
461 | ||
462 | // aliasing | |
463 | template< class Y > | |
b32b8144 | 464 | shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) |
7c673cae FG |
465 | { |
466 | } | |
467 | ||
468 | #ifndef BOOST_NO_AUTO_PTR | |
469 | ||
470 | template<class Y> | |
471 | explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn() | |
472 | { | |
473 | boost::detail::sp_assert_convertible< Y, T >(); | |
474 | ||
475 | Y * tmp = r.get(); | |
476 | pn = boost::detail::shared_count( r ); | |
477 | ||
478 | boost::detail::sp_deleter_construct( this, tmp ); | |
479 | } | |
480 | ||
481 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
482 | ||
483 | template<class Y> | |
484 | shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn() | |
485 | { | |
486 | boost::detail::sp_assert_convertible< Y, T >(); | |
487 | ||
488 | Y * tmp = r.get(); | |
489 | pn = boost::detail::shared_count( r ); | |
490 | ||
491 | boost::detail::sp_deleter_construct( this, tmp ); | |
492 | } | |
493 | ||
494 | #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
495 | ||
496 | template<class Ap> | |
497 | explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn() | |
498 | { | |
499 | typedef typename Ap::element_type Y; | |
500 | ||
501 | boost::detail::sp_assert_convertible< Y, T >(); | |
502 | ||
503 | Y * tmp = r.get(); | |
504 | pn = boost::detail::shared_count( r ); | |
505 | ||
506 | boost::detail::sp_deleter_construct( this, tmp ); | |
507 | } | |
508 | ||
509 | #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
510 | ||
511 | #endif // BOOST_NO_AUTO_PTR | |
512 | ||
513 | #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
514 | ||
515 | template< class Y, class D > | |
516 | shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn() | |
517 | { | |
518 | boost::detail::sp_assert_convertible< Y, T >(); | |
519 | ||
520 | typename std::unique_ptr< Y, D >::pointer tmp = r.get(); | |
7c673cae | 521 | |
b32b8144 FG |
522 | if( tmp != 0 ) |
523 | { | |
524 | pn = boost::detail::shared_count( r ); | |
525 | boost::detail::sp_deleter_construct( this, tmp ); | |
526 | } | |
7c673cae FG |
527 | } |
528 | ||
529 | #endif | |
530 | ||
531 | template< class Y, class D > | |
532 | shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn() | |
533 | { | |
534 | boost::detail::sp_assert_convertible< Y, T >(); | |
535 | ||
536 | typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get(); | |
7c673cae | 537 | |
b32b8144 FG |
538 | if( tmp != 0 ) |
539 | { | |
540 | pn = boost::detail::shared_count( r ); | |
541 | boost::detail::sp_deleter_construct( this, tmp ); | |
542 | } | |
7c673cae FG |
543 | } |
544 | ||
545 | // assignment | |
546 | ||
b32b8144 | 547 | shared_ptr & operator=( shared_ptr const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
548 | { |
549 | this_type(r).swap(*this); | |
550 | return *this; | |
551 | } | |
552 | ||
553 | #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) | |
554 | ||
555 | template<class Y> | |
b32b8144 | 556 | shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPT |
7c673cae FG |
557 | { |
558 | this_type(r).swap(*this); | |
559 | return *this; | |
560 | } | |
561 | ||
562 | #endif | |
563 | ||
564 | #ifndef BOOST_NO_AUTO_PTR | |
565 | ||
566 | template<class Y> | |
567 | shared_ptr & operator=( std::auto_ptr<Y> & r ) | |
568 | { | |
569 | this_type( r ).swap( *this ); | |
570 | return *this; | |
571 | } | |
572 | ||
573 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
574 | ||
575 | template<class Y> | |
576 | shared_ptr & operator=( std::auto_ptr<Y> && r ) | |
577 | { | |
578 | this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this ); | |
579 | return *this; | |
580 | } | |
581 | ||
582 | #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | |
583 | ||
584 | template<class Ap> | |
585 | typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) | |
586 | { | |
587 | this_type( r ).swap( *this ); | |
588 | return *this; | |
589 | } | |
590 | ||
591 | #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | |
592 | ||
593 | #endif // BOOST_NO_AUTO_PTR | |
594 | ||
595 | #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
596 | ||
597 | template<class Y, class D> | |
598 | shared_ptr & operator=( std::unique_ptr<Y, D> && r ) | |
599 | { | |
600 | this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this); | |
601 | return *this; | |
602 | } | |
603 | ||
604 | #endif | |
605 | ||
606 | template<class Y, class D> | |
607 | shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r ) | |
608 | { | |
609 | // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this ); | |
610 | ||
611 | boost::detail::sp_assert_convertible< Y, T >(); | |
612 | ||
613 | typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get(); | |
614 | ||
615 | shared_ptr tmp; | |
616 | ||
b32b8144 FG |
617 | if( p != 0 ) |
618 | { | |
619 | tmp.px = p; | |
620 | tmp.pn = boost::detail::shared_count( r ); | |
7c673cae | 621 | |
b32b8144 FG |
622 | boost::detail::sp_deleter_construct( &tmp, p ); |
623 | } | |
7c673cae FG |
624 | |
625 | tmp.swap( *this ); | |
626 | ||
627 | return *this; | |
628 | } | |
629 | ||
630 | // Move support | |
631 | ||
632 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
633 | ||
b32b8144 | 634 | shared_ptr( shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn() |
7c673cae FG |
635 | { |
636 | pn.swap( r.pn ); | |
637 | r.px = 0; | |
638 | } | |
639 | ||
640 | template<class Y> | |
641 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | |
642 | ||
643 | shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() ) | |
644 | ||
645 | #else | |
646 | ||
647 | shared_ptr( shared_ptr<Y> && r ) | |
648 | ||
649 | #endif | |
b32b8144 | 650 | BOOST_SP_NOEXCEPT : px( r.px ), pn() |
7c673cae FG |
651 | { |
652 | boost::detail::sp_assert_convertible< Y, T >(); | |
653 | ||
654 | pn.swap( r.pn ); | |
655 | r.px = 0; | |
656 | } | |
657 | ||
b32b8144 | 658 | shared_ptr & operator=( shared_ptr && r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
659 | { |
660 | this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); | |
661 | return *this; | |
662 | } | |
663 | ||
664 | template<class Y> | |
b32b8144 | 665 | shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
666 | { |
667 | this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this ); | |
668 | return *this; | |
669 | } | |
670 | ||
671 | // aliasing move | |
672 | template<class Y> | |
b32b8144 | 673 | shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn() |
7c673cae FG |
674 | { |
675 | pn.swap( r.pn ); | |
676 | r.px = 0; | |
677 | } | |
678 | ||
679 | #endif | |
680 | ||
681 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
682 | ||
b32b8144 | 683 | shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT |
7c673cae FG |
684 | { |
685 | this_type().swap(*this); | |
686 | return *this; | |
687 | } | |
688 | ||
689 | #endif | |
690 | ||
b32b8144 | 691 | void reset() BOOST_SP_NOEXCEPT |
7c673cae FG |
692 | { |
693 | this_type().swap(*this); | |
694 | } | |
695 | ||
696 | template<class Y> void reset( Y * p ) // Y must be complete | |
697 | { | |
698 | BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors | |
699 | this_type( p ).swap( *this ); | |
700 | } | |
701 | ||
702 | template<class Y, class D> void reset( Y * p, D d ) | |
703 | { | |
704 | this_type( p, d ).swap( *this ); | |
705 | } | |
706 | ||
707 | template<class Y, class D, class A> void reset( Y * p, D d, A a ) | |
708 | { | |
709 | this_type( p, d, a ).swap( *this ); | |
710 | } | |
711 | ||
b32b8144 | 712 | template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
713 | { |
714 | this_type( r, p ).swap( *this ); | |
715 | } | |
716 | ||
717 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
718 | ||
b32b8144 | 719 | template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
720 | { |
721 | this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this ); | |
722 | } | |
723 | ||
724 | #endif | |
725 | ||
b32b8144 | 726 | typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT |
7c673cae FG |
727 | { |
728 | BOOST_ASSERT( px != 0 ); | |
729 | return *px; | |
730 | } | |
731 | ||
b32b8144 | 732 | typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT |
7c673cae FG |
733 | { |
734 | BOOST_ASSERT( px != 0 ); | |
735 | return px; | |
736 | } | |
737 | ||
b32b8144 | 738 | typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT |
7c673cae FG |
739 | { |
740 | BOOST_ASSERT( px != 0 ); | |
741 | BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) ); | |
742 | ||
743 | return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] ); | |
744 | } | |
745 | ||
b32b8144 | 746 | element_type * get() const BOOST_SP_NOEXCEPT |
7c673cae FG |
747 | { |
748 | return px; | |
749 | } | |
750 | ||
751 | // implicit conversion to "bool" | |
752 | #include <boost/smart_ptr/detail/operator_bool.hpp> | |
753 | ||
b32b8144 | 754 | bool unique() const BOOST_SP_NOEXCEPT |
7c673cae FG |
755 | { |
756 | return pn.unique(); | |
757 | } | |
758 | ||
b32b8144 | 759 | long use_count() const BOOST_SP_NOEXCEPT |
7c673cae FG |
760 | { |
761 | return pn.use_count(); | |
762 | } | |
763 | ||
b32b8144 | 764 | void swap( shared_ptr & other ) BOOST_SP_NOEXCEPT |
7c673cae FG |
765 | { |
766 | std::swap(px, other.px); | |
767 | pn.swap(other.pn); | |
768 | } | |
769 | ||
b32b8144 | 770 | template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT |
7c673cae FG |
771 | { |
772 | return pn < rhs.pn; | |
773 | } | |
774 | ||
b32b8144 | 775 | template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT |
7c673cae FG |
776 | { |
777 | return pn < rhs.pn; | |
778 | } | |
779 | ||
92f5a8d4 | 780 | void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT |
7c673cae FG |
781 | { |
782 | return pn.get_deleter( ti ); | |
783 | } | |
784 | ||
92f5a8d4 | 785 | void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT |
b32b8144 FG |
786 | { |
787 | return pn.get_local_deleter( ti ); | |
788 | } | |
789 | ||
790 | void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPT | |
7c673cae FG |
791 | { |
792 | return pn.get_untyped_deleter(); | |
793 | } | |
794 | ||
b32b8144 | 795 | bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPT |
7c673cae FG |
796 | { |
797 | return px == r.px && pn == r.pn; | |
798 | } | |
799 | ||
92f5a8d4 | 800 | boost::detail::shared_count _internal_count() const BOOST_SP_NOEXCEPT |
b32b8144 FG |
801 | { |
802 | return pn; | |
803 | } | |
804 | ||
7c673cae FG |
805 | // Tasteless as this may seem, making all members public allows member templates |
806 | // to work in the absence of member template friends. (Matthew Langston) | |
807 | ||
808 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS | |
809 | ||
810 | private: | |
811 | ||
812 | template<class Y> friend class shared_ptr; | |
813 | template<class Y> friend class weak_ptr; | |
814 | ||
815 | ||
816 | #endif | |
817 | ||
818 | element_type * px; // contained pointer | |
819 | boost::detail::shared_count pn; // reference counter | |
820 | ||
821 | }; // shared_ptr | |
822 | ||
b32b8144 | 823 | template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
824 | { |
825 | return a.get() == b.get(); | |
826 | } | |
827 | ||
b32b8144 | 828 | template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
829 | { |
830 | return a.get() != b.get(); | |
831 | } | |
832 | ||
833 | #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 | |
834 | ||
835 | // Resolve the ambiguity between our op!= and the one in rel_ops | |
836 | ||
b32b8144 | 837 | template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
838 | { |
839 | return a.get() != b.get(); | |
840 | } | |
841 | ||
842 | #endif | |
843 | ||
844 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
845 | ||
b32b8144 | 846 | template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT |
7c673cae FG |
847 | { |
848 | return p.get() == 0; | |
849 | } | |
850 | ||
b32b8144 | 851 | template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
852 | { |
853 | return p.get() == 0; | |
854 | } | |
855 | ||
b32b8144 | 856 | template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT |
7c673cae FG |
857 | { |
858 | return p.get() != 0; | |
859 | } | |
860 | ||
b32b8144 | 861 | template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
862 | { |
863 | return p.get() != 0; | |
864 | } | |
865 | ||
866 | #endif | |
867 | ||
b32b8144 | 868 | template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
869 | { |
870 | return a.owner_before( b ); | |
871 | } | |
872 | ||
b32b8144 | 873 | template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
874 | { |
875 | a.swap(b); | |
876 | } | |
877 | ||
b32b8144 | 878 | template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
879 | { |
880 | (void) static_cast< T* >( static_cast< U* >( 0 ) ); | |
881 | ||
882 | typedef typename shared_ptr<T>::element_type E; | |
883 | ||
884 | E * p = static_cast< E* >( r.get() ); | |
885 | return shared_ptr<T>( r, p ); | |
886 | } | |
887 | ||
b32b8144 | 888 | template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
889 | { |
890 | (void) const_cast< T* >( static_cast< U* >( 0 ) ); | |
891 | ||
892 | typedef typename shared_ptr<T>::element_type E; | |
893 | ||
894 | E * p = const_cast< E* >( r.get() ); | |
895 | return shared_ptr<T>( r, p ); | |
896 | } | |
897 | ||
b32b8144 | 898 | template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
899 | { |
900 | (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); | |
901 | ||
902 | typedef typename shared_ptr<T>::element_type E; | |
903 | ||
904 | E * p = dynamic_cast< E* >( r.get() ); | |
905 | return p? shared_ptr<T>( r, p ): shared_ptr<T>(); | |
906 | } | |
907 | ||
b32b8144 | 908 | template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
909 | { |
910 | (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); | |
911 | ||
912 | typedef typename shared_ptr<T>::element_type E; | |
913 | ||
914 | E * p = reinterpret_cast< E* >( r.get() ); | |
915 | return shared_ptr<T>( r, p ); | |
916 | } | |
917 | ||
b32b8144 FG |
918 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) |
919 | ||
920 | template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT | |
921 | { | |
922 | (void) static_cast< T* >( static_cast< U* >( 0 ) ); | |
923 | ||
924 | typedef typename shared_ptr<T>::element_type E; | |
925 | ||
926 | E * p = static_cast< E* >( r.get() ); | |
927 | return shared_ptr<T>( std::move(r), p ); | |
928 | } | |
929 | ||
930 | template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT | |
931 | { | |
932 | (void) const_cast< T* >( static_cast< U* >( 0 ) ); | |
933 | ||
934 | typedef typename shared_ptr<T>::element_type E; | |
935 | ||
936 | E * p = const_cast< E* >( r.get() ); | |
937 | return shared_ptr<T>( std::move(r), p ); | |
938 | } | |
939 | ||
940 | template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT | |
941 | { | |
942 | (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); | |
943 | ||
944 | typedef typename shared_ptr<T>::element_type E; | |
945 | ||
946 | E * p = dynamic_cast< E* >( r.get() ); | |
947 | return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>(); | |
948 | } | |
949 | ||
950 | template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT | |
951 | { | |
952 | (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); | |
953 | ||
954 | typedef typename shared_ptr<T>::element_type E; | |
955 | ||
956 | E * p = reinterpret_cast< E* >( r.get() ); | |
957 | return shared_ptr<T>( std::move(r), p ); | |
958 | } | |
959 | ||
960 | #endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
961 | ||
7c673cae FG |
962 | // get_pointer() enables boost::mem_fn to recognize shared_ptr |
963 | ||
b32b8144 | 964 | template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPT |
7c673cae FG |
965 | { |
966 | return p.get(); | |
967 | } | |
968 | ||
969 | // operator<< | |
970 | ||
971 | #if !defined(BOOST_NO_IOSTREAM) | |
972 | ||
973 | #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) | |
974 | ||
975 | template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p) | |
976 | { | |
977 | os << p.get(); | |
978 | return os; | |
979 | } | |
980 | ||
981 | #else | |
982 | ||
983 | // in STLport's no-iostreams mode no iostream symbols can be used | |
984 | #ifndef _STLP_NO_IOSTREAMS | |
985 | ||
986 | # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) | |
987 | // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL | |
988 | using std::basic_ostream; | |
989 | template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p) | |
990 | # else | |
991 | template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p) | |
992 | # endif | |
993 | { | |
994 | os << p.get(); | |
995 | return os; | |
996 | } | |
997 | ||
998 | #endif // _STLP_NO_IOSTREAMS | |
999 | ||
1000 | #endif // __GNUC__ < 3 | |
1001 | ||
1002 | #endif // !defined(BOOST_NO_IOSTREAM) | |
1003 | ||
1004 | // get_deleter | |
1005 | ||
1006 | namespace detail | |
1007 | { | |
1008 | ||
b32b8144 | 1009 | template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae | 1010 | { |
92f5a8d4 | 1011 | return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)) ); |
7c673cae FG |
1012 | } |
1013 | ||
b32b8144 FG |
1014 | template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT; |
1015 | template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT; | |
7c673cae FG |
1016 | |
1017 | class esft2_deleter_wrapper | |
1018 | { | |
1019 | private: | |
1020 | ||
1021 | shared_ptr<void const volatile> deleter_; | |
1022 | ||
1023 | public: | |
1024 | ||
92f5a8d4 | 1025 | esft2_deleter_wrapper() BOOST_SP_NOEXCEPT |
7c673cae FG |
1026 | { |
1027 | } | |
1028 | ||
b32b8144 | 1029 | template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1030 | { |
1031 | deleter_ = deleter; | |
1032 | } | |
1033 | ||
b32b8144 | 1034 | template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPT |
7c673cae FG |
1035 | { |
1036 | return boost::detail::basic_get_deleter<D>( deleter_ ); | |
1037 | } | |
1038 | ||
b32b8144 | 1039 | template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT |
7c673cae FG |
1040 | { |
1041 | BOOST_ASSERT( deleter_.use_count() <= 1 ); | |
1042 | deleter_.reset(); | |
1043 | } | |
1044 | }; | |
1045 | ||
1046 | } // namespace detail | |
1047 | ||
b32b8144 | 1048 | template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae | 1049 | { |
b32b8144 FG |
1050 | D * d = boost::detail::basic_get_deleter<D>( p ); |
1051 | ||
1052 | if( d == 0 ) | |
1053 | { | |
1054 | d = boost::detail::basic_get_local_deleter( d, p ); | |
1055 | } | |
7c673cae | 1056 | |
b32b8144 | 1057 | if( d == 0 ) |
7c673cae FG |
1058 | { |
1059 | boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p); | |
1060 | // The following get_deleter method call is fully qualified because | |
1061 | // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>() | |
b32b8144 | 1062 | if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>(); |
7c673cae FG |
1063 | } |
1064 | ||
b32b8144 | 1065 | return d; |
7c673cae FG |
1066 | } |
1067 | ||
1068 | // atomic access | |
1069 | ||
1070 | #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) | |
1071 | ||
b32b8144 | 1072 | template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1073 | { |
1074 | return false; | |
1075 | } | |
1076 | ||
b32b8144 | 1077 | template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1078 | { |
1079 | boost::detail::spinlock_pool<2>::scoped_lock lock( p ); | |
1080 | return *p; | |
1081 | } | |
1082 | ||
11fdf7f2 | 1083 | template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1084 | { |
1085 | return atomic_load( p ); | |
1086 | } | |
1087 | ||
b32b8144 | 1088 | template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1089 | { |
1090 | boost::detail::spinlock_pool<2>::scoped_lock lock( p ); | |
1091 | p->swap( r ); | |
1092 | } | |
1093 | ||
11fdf7f2 | 1094 | template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1095 | { |
1096 | atomic_store( p, r ); // std::move( r ) | |
1097 | } | |
1098 | ||
b32b8144 | 1099 | template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1100 | { |
1101 | boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); | |
1102 | ||
1103 | sp.lock(); | |
1104 | p->swap( r ); | |
1105 | sp.unlock(); | |
1106 | ||
1107 | return r; // return std::move( r ) | |
1108 | } | |
1109 | ||
11fdf7f2 | 1110 | template<class T, class M> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1111 | { |
1112 | return atomic_exchange( p, r ); // std::move( r ) | |
1113 | } | |
1114 | ||
b32b8144 | 1115 | template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1116 | { |
1117 | boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); | |
1118 | ||
1119 | sp.lock(); | |
1120 | ||
1121 | if( p->_internal_equiv( *v ) ) | |
1122 | { | |
1123 | p->swap( w ); | |
1124 | ||
1125 | sp.unlock(); | |
1126 | ||
1127 | return true; | |
1128 | } | |
1129 | else | |
1130 | { | |
1131 | shared_ptr<T> tmp( *p ); | |
1132 | ||
1133 | sp.unlock(); | |
1134 | ||
1135 | tmp.swap( *v ); | |
1136 | return false; | |
1137 | } | |
1138 | } | |
1139 | ||
11fdf7f2 | 1140 | template<class T, class M> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ M, /*memory_order failure*/ M ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1141 | { |
1142 | return atomic_compare_exchange( p, v, w ); // std::move( w ) | |
1143 | } | |
1144 | ||
1145 | #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS) | |
1146 | ||
1147 | // hash_value | |
1148 | ||
1149 | template< class T > struct hash; | |
1150 | ||
b32b8144 | 1151 | template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
1152 | { |
1153 | return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() ); | |
1154 | } | |
1155 | ||
1156 | } // namespace boost | |
1157 | ||
b32b8144 FG |
1158 | #include <boost/smart_ptr/detail/local_sp_deleter.hpp> |
1159 | ||
1160 | namespace boost | |
1161 | { | |
1162 | ||
1163 | namespace detail | |
1164 | { | |
1165 | ||
1166 | template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT | |
1167 | { | |
92f5a8d4 | 1168 | return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) ); |
b32b8144 FG |
1169 | } |
1170 | ||
1171 | template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT | |
1172 | { | |
92f5a8d4 | 1173 | return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) ); |
b32b8144 FG |
1174 | } |
1175 | ||
1176 | } // namespace detail | |
1177 | ||
1178 | } // namespace boost | |
1179 | ||
7c673cae FG |
1180 | #if defined( BOOST_SP_DISABLE_DEPRECATED ) |
1181 | #pragma GCC diagnostic pop | |
1182 | #endif | |
1183 | ||
1184 | #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED |