Line data Source code
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 : //
14 : // See http://www.boost.org/libs/smart_ptr/ for documentation.
15 : //
16 :
17 : #include <boost/smart_ptr/detail/shared_count.hpp>
18 : #include <boost/smart_ptr/detail/sp_convertible.hpp>
19 : #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
20 : #include <boost/smart_ptr/detail/sp_noexcept.hpp>
21 : #include <boost/core/checked_delete.hpp>
22 : #include <boost/throw_exception.hpp>
23 : #include <boost/assert.hpp>
24 : #include <boost/config.hpp>
25 : #include <boost/config/workaround.hpp>
26 :
27 : #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
28 : #include <boost/smart_ptr/detail/spinlock_pool.hpp>
29 : #endif
30 :
31 : #include <algorithm> // for std::swap
32 : #include <functional> // for std::less
33 : #include <typeinfo> // for std::bad_cast
34 : #include <cstddef> // for std::size_t
35 : #include <memory> // for std::auto_ptr
36 : #include <iosfwd> // for std::basic_ostream
37 :
38 : #if defined( BOOST_SP_DISABLE_DEPRECATED )
39 : #pragma GCC diagnostic push
40 : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
41 : #endif
42 :
43 : namespace boost
44 : {
45 :
46 : template<class T> class shared_ptr;
47 : template<class T> class weak_ptr;
48 : template<class T> class enable_shared_from_this;
49 : class enable_shared_from_raw;
50 :
51 : namespace movelib
52 : {
53 :
54 : template< class T, class D > class unique_ptr;
55 :
56 : } // namespace movelib
57 :
58 : namespace detail
59 : {
60 :
61 : // sp_element, element_type
62 :
63 : template< class T > struct sp_element
64 : {
65 : typedef T type;
66 : };
67 :
68 : template< class T > struct sp_element< T[] >
69 : {
70 : typedef T type;
71 : };
72 :
73 : template< class T, std::size_t N > struct sp_element< T[N] >
74 : {
75 : typedef T type;
76 : };
77 :
78 : // sp_dereference, return type of operator*
79 :
80 : template< class T > struct sp_dereference
81 : {
82 : typedef T & type;
83 : };
84 :
85 : template<> struct sp_dereference< void >
86 : {
87 : typedef void type;
88 : };
89 :
90 : template<> struct sp_dereference< void const >
91 : {
92 : typedef void type;
93 : };
94 :
95 : template<> struct sp_dereference< void volatile >
96 : {
97 : typedef void type;
98 : };
99 :
100 : template<> struct sp_dereference< void const volatile >
101 : {
102 : typedef void type;
103 : };
104 :
105 : template< class T > struct sp_dereference< T[] >
106 : {
107 : typedef void type;
108 : };
109 :
110 : template< class T, std::size_t N > struct sp_dereference< T[N] >
111 : {
112 : typedef void type;
113 : };
114 :
115 : // sp_member_access, return type of operator->
116 :
117 : template< class T > struct sp_member_access
118 : {
119 : typedef T * type;
120 : };
121 :
122 : template< class T > struct sp_member_access< T[] >
123 : {
124 : typedef void type;
125 : };
126 :
127 : template< class T, std::size_t N > struct sp_member_access< T[N] >
128 : {
129 : typedef void type;
130 : };
131 :
132 : // sp_array_access, return type of operator[]
133 :
134 : template< class T > struct sp_array_access
135 : {
136 : typedef void type;
137 : };
138 :
139 : template< class T > struct sp_array_access< T[] >
140 : {
141 : typedef T & type;
142 : };
143 :
144 : template< class T, std::size_t N > struct sp_array_access< T[N] >
145 : {
146 : typedef T & type;
147 : };
148 :
149 : // sp_extent, for operator[] index check
150 :
151 : template< class T > struct sp_extent
152 : {
153 : enum _vt { value = 0 };
154 : };
155 :
156 : template< class T, std::size_t N > struct sp_extent< T[N] >
157 : {
158 : enum _vt { value = N };
159 : };
160 :
161 : // enable_shared_from_this support
162 :
163 : 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 )
164 : {
165 : if( pe != 0 )
166 : {
167 : pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
168 : }
169 : }
170 :
171 : 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 );
172 :
173 : #ifdef _MANAGED
174 :
175 : // Avoid C4793, ... causes native code generation
176 :
177 : struct sp_any_pointer
178 : {
179 : template<class T> sp_any_pointer( T* ) {}
180 : };
181 :
182 : inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
183 : {
184 : }
185 :
186 : #else // _MANAGED
187 :
188 720351 : inline void sp_enable_shared_from_this( ... )
189 : {
190 720351 : }
191 :
192 : #endif // _MANAGED
193 :
194 : // sp_assert_convertible
195 :
196 53911 : template< class Y, class T > inline void sp_assert_convertible() noexcept
197 : {
198 : static_assert( sp_convertible< Y, T >::value, "incompatible pointer type" );
199 53911 : }
200 :
201 : // pointer constructor helper
202 :
203 481263 : template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
204 : {
205 481263 : boost::detail::shared_count( p ).swap( pn );
206 481263 : boost::detail::sp_enable_shared_from_this( ppx, p, p );
207 481263 : }
208 :
209 : template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
210 : {
211 : sp_assert_convertible< Y[], T[] >();
212 : boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
213 : }
214 :
215 : 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 )
216 : {
217 : sp_assert_convertible< Y[N], T[N] >();
218 : boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
219 : }
220 :
221 : // deleter constructor helper
222 :
223 119544 : template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
224 : {
225 119544 : boost::detail::sp_enable_shared_from_this( ppx, p, p );
226 119544 : }
227 :
228 : template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
229 : {
230 : sp_assert_convertible< Y[], T[] >();
231 : }
232 :
233 : template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
234 : {
235 : sp_assert_convertible< Y[N], T[N] >();
236 : }
237 :
238 : struct sp_internal_constructor_tag
239 : {
240 : };
241 :
242 : } // namespace detail
243 :
244 :
245 : //
246 : // shared_ptr
247 : //
248 : // An enhanced relative of scoped_ptr with reference counted copy semantics.
249 : // The object pointed to is deleted when the last shared_ptr pointing to it
250 : // is destroyed or reset.
251 : //
252 :
253 : template<class T> class shared_ptr
254 : {
255 : private:
256 :
257 : // Borland 5.5.1 specific workaround
258 : typedef shared_ptr<T> this_type;
259 :
260 : public:
261 :
262 : typedef typename boost::detail::sp_element< T >::type element_type;
263 :
264 19943300 : constexpr shared_ptr() noexcept : px( 0 ), pn()
265 9971650 : {
266 19943300 : }
267 :
268 : constexpr shared_ptr( std::nullptr_t ) noexcept : px( 0 ), pn()
269 : {
270 : }
271 :
272 : constexpr shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) noexcept : px( px_ ), pn( pn_ )
273 : {
274 : }
275 :
276 : constexpr shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) noexcept : px( px_ ), pn( std::move( pn_ ) )
277 : {
278 : }
279 :
280 : template<class Y>
281 962526 : explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
282 481263 : {
283 481263 : boost::detail::sp_pointer_construct( this, p, pn );
284 962526 : }
285 :
286 : //
287 : // Requirements: D's copy/move constructors must not throw
288 : //
289 : // shared_ptr will release p by calling d(p)
290 : //
291 :
292 239088 : template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
293 119544 : {
294 119544 : boost::detail::sp_deleter_construct( this, p );
295 239088 : }
296 :
297 : template<class D> shared_ptr( std::nullptr_t p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
298 : {
299 : }
300 :
301 : // As above, but with allocator. A's copy constructor shall not throw.
302 :
303 : template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
304 : {
305 : boost::detail::sp_deleter_construct( this, p );
306 : }
307 :
308 : template<class D, class A> shared_ptr( std::nullptr_t p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
309 : {
310 : }
311 :
312 : // generated copy constructor, destructor are fine...
313 : // ... except in C++0x, move disables the implicit copy
314 :
315 3124326 : shared_ptr( shared_ptr const & r ) noexcept : px( r.px ), pn( r.pn )
316 1562163 : {
317 3124326 : }
318 :
319 : template<class Y>
320 : explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
321 : {
322 : boost::detail::sp_assert_convertible< Y, T >();
323 :
324 : // it is now safe to copy r.px, as pn(r.pn) did not throw
325 : px = r.px;
326 : }
327 :
328 : template<class Y>
329 430784 : shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
330 215392 : noexcept : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
331 215392 : {
332 215392 : if( !pn.empty() )
333 : {
334 213455 : px = r.px;
335 213455 : }
336 430784 : }
337 :
338 : template<class Y>
339 21756 : shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
340 10878 : noexcept : px( r.px ), pn( r.pn )
341 10878 : {
342 10878 : boost::detail::sp_assert_convertible< Y, T >();
343 21756 : }
344 :
345 : // aliasing
346 : template< class Y >
347 239088 : shared_ptr( shared_ptr<Y> const & r, element_type * p ) noexcept : px( p ), pn( r.pn )
348 119544 : {
349 239088 : }
350 :
351 : #ifndef BOOST_NO_AUTO_PTR
352 :
353 : template<class Y>
354 : explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
355 : {
356 : boost::detail::sp_assert_convertible< Y, T >();
357 :
358 : Y * tmp = r.get();
359 : pn = boost::detail::shared_count( r );
360 :
361 : boost::detail::sp_deleter_construct( this, tmp );
362 : }
363 :
364 : template<class Y>
365 : shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
366 : {
367 : boost::detail::sp_assert_convertible< Y, T >();
368 :
369 : Y * tmp = r.get();
370 : pn = boost::detail::shared_count( r );
371 :
372 : boost::detail::sp_deleter_construct( this, tmp );
373 : }
374 :
375 : #endif // BOOST_NO_AUTO_PTR
376 :
377 : template< class Y, class D >
378 : shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
379 : {
380 : boost::detail::sp_assert_convertible< Y, T >();
381 :
382 : typename std::unique_ptr< Y, D >::pointer tmp = r.get();
383 :
384 : if( tmp != 0 )
385 : {
386 : pn = boost::detail::shared_count( r );
387 : boost::detail::sp_deleter_construct( this, tmp );
388 : }
389 : }
390 :
391 : template< class Y, class D >
392 : shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
393 : {
394 : boost::detail::sp_assert_convertible< Y, T >();
395 :
396 : typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
397 :
398 : if( tmp != 0 )
399 : {
400 : pn = boost::detail::shared_count( r );
401 : boost::detail::sp_deleter_construct( this, tmp );
402 : }
403 : }
404 :
405 : // assignment
406 :
407 1131559 : shared_ptr & operator=( shared_ptr const & r ) noexcept
408 : {
409 1131559 : this_type(r).swap(*this);
410 1131559 : return *this;
411 : }
412 :
413 : template<class Y>
414 : shared_ptr & operator=(shared_ptr<Y> const & r) noexcept
415 : {
416 : this_type(r).swap(*this);
417 : return *this;
418 : }
419 :
420 : #ifndef BOOST_NO_AUTO_PTR
421 :
422 : template<class Y>
423 : shared_ptr & operator=( std::auto_ptr<Y> & r )
424 : {
425 : this_type( r ).swap( *this );
426 : return *this;
427 : }
428 :
429 : template<class Y>
430 : shared_ptr & operator=( std::auto_ptr<Y> && r )
431 : {
432 : this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
433 : return *this;
434 : }
435 :
436 : #endif // BOOST_NO_AUTO_PTR
437 :
438 : template<class Y, class D>
439 : shared_ptr & operator=( std::unique_ptr<Y, D> && r )
440 : {
441 : this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
442 : return *this;
443 : }
444 :
445 : template<class Y, class D>
446 : shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
447 : {
448 : // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
449 :
450 : boost::detail::sp_assert_convertible< Y, T >();
451 :
452 : typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
453 :
454 : shared_ptr tmp;
455 :
456 : if( p != 0 )
457 : {
458 : tmp.px = p;
459 : tmp.pn = boost::detail::shared_count( r );
460 :
461 : boost::detail::sp_deleter_construct( &tmp, p );
462 : }
463 :
464 : tmp.swap( *this );
465 :
466 : return *this;
467 : }
468 :
469 : // Move support
470 :
471 764004 : shared_ptr( shared_ptr && r ) noexcept : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) )
472 382002 : {
473 382002 : r.px = 0;
474 764004 : }
475 :
476 : template<class Y>
477 : shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
478 : noexcept : px( r.px ), pn( static_cast< boost::detail::shared_count && >( r.pn ) )
479 : {
480 : boost::detail::sp_assert_convertible< Y, T >();
481 : r.px = 0;
482 : }
483 :
484 105412 : shared_ptr & operator=( shared_ptr && r ) noexcept
485 : {
486 105412 : this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
487 105412 : return *this;
488 : }
489 :
490 : template<class Y>
491 : shared_ptr & operator=( shared_ptr<Y> && r ) noexcept
492 : {
493 : this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
494 : return *this;
495 : }
496 :
497 : // aliasing move
498 : template<class Y>
499 : shared_ptr( shared_ptr<Y> && r, element_type * p ) noexcept : px( p ), pn()
500 : {
501 : pn.swap( r.pn );
502 : r.px = 0;
503 : }
504 :
505 : shared_ptr & operator=( std::nullptr_t ) noexcept
506 : {
507 : this_type().swap(*this);
508 : return *this;
509 : }
510 :
511 19871 : void reset() noexcept
512 : {
513 19871 : this_type().swap(*this);
514 19871 : }
515 :
516 1022 : template<class Y> void reset( Y * p ) // Y must be complete
517 : {
518 1022 : BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
519 1022 : this_type( p ).swap( *this );
520 1022 : }
521 :
522 : template<class Y, class D> void reset( Y * p, D d )
523 : {
524 : this_type( p, static_cast< D&& >( d ) ).swap( *this );
525 : }
526 :
527 : template<class Y, class D, class A> void reset( Y * p, D d, A a )
528 : {
529 : this_type( p, static_cast< D&& >( d ), a ).swap( *this );
530 : }
531 :
532 : template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) noexcept
533 : {
534 : this_type( r, p ).swap( *this );
535 : }
536 :
537 : template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) noexcept
538 : {
539 : this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this );
540 : }
541 :
542 14017126 : typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT
543 : {
544 14017126 : BOOST_ASSERT( px != 0 );
545 14017126 : return *px;
546 : }
547 :
548 54037310 : typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT
549 : {
550 54037310 : BOOST_ASSERT( px != 0 );
551 54037310 : return px;
552 : }
553 :
554 : typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
555 : {
556 : BOOST_ASSERT( px != 0 );
557 : BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
558 :
559 : return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
560 : }
561 :
562 384089 : element_type * get() const noexcept
563 : {
564 384089 : return px;
565 : }
566 :
567 9193138 : explicit operator bool () const noexcept
568 : {
569 9193138 : return px != 0;
570 : }
571 :
572 3224272 : bool unique() const noexcept
573 : {
574 3224272 : return pn.unique();
575 : }
576 :
577 : long use_count() const noexcept
578 : {
579 : return pn.use_count();
580 : }
581 :
582 1257863 : void swap( shared_ptr & other ) noexcept
583 : {
584 1257863 : std::swap(px, other.px);
585 1257863 : pn.swap(other.pn);
586 1257863 : }
587 :
588 : template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const noexcept
589 : {
590 : return pn < rhs.pn;
591 : }
592 :
593 : template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const noexcept
594 : {
595 : return pn < rhs.pn;
596 : }
597 :
598 : template<class Y> bool owner_equals( shared_ptr<Y> const & rhs ) const noexcept
599 : {
600 : return pn == rhs.pn;
601 : }
602 :
603 : template<class Y> bool owner_equals( weak_ptr<Y> const & rhs ) const noexcept
604 : {
605 : return pn == rhs.pn;
606 : }
607 :
608 : std::size_t owner_hash_value() const noexcept
609 : {
610 : return pn.hash_value();
611 : }
612 :
613 : void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const noexcept
614 : {
615 : return pn.get_deleter( ti );
616 : }
617 :
618 : void * _internal_get_local_deleter( boost::detail::sp_typeinfo_ const & ti ) const noexcept
619 : {
620 : return pn.get_local_deleter( ti );
621 : }
622 :
623 119544 : void * _internal_get_untyped_deleter() const noexcept
624 : {
625 119544 : return pn.get_untyped_deleter();
626 : }
627 :
628 : bool _internal_equiv( shared_ptr const & r ) const noexcept
629 : {
630 : return px == r.px && pn == r.pn;
631 : }
632 :
633 : boost::detail::shared_count _internal_count() const noexcept
634 : {
635 : return pn;
636 : }
637 :
638 : private:
639 :
640 : template<class Y> friend class shared_ptr;
641 : template<class Y> friend class weak_ptr;
642 :
643 :
644 : element_type * px; // contained pointer
645 : boost::detail::shared_count pn; // reference counter
646 :
647 : }; // shared_ptr
648 :
649 : template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept
650 : {
651 : return a.get() == b.get();
652 : }
653 :
654 : template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept
655 : {
656 : return a.get() != b.get();
657 : }
658 :
659 6186 : template<class T> inline bool operator==( shared_ptr<T> const & p, std::nullptr_t ) noexcept
660 : {
661 6186 : return p.get() == 0;
662 : }
663 :
664 : template<class T> inline bool operator==( std::nullptr_t, shared_ptr<T> const & p ) noexcept
665 : {
666 : return p.get() == 0;
667 : }
668 :
669 : template<class T> inline bool operator!=( shared_ptr<T> const & p, std::nullptr_t ) noexcept
670 : {
671 : return p.get() != 0;
672 : }
673 :
674 : template<class T> inline bool operator!=( std::nullptr_t, shared_ptr<T> const & p ) noexcept
675 : {
676 : return p.get() != 0;
677 : }
678 :
679 : template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept
680 : {
681 : return a.owner_before( b );
682 : }
683 :
684 : template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept
685 : {
686 : a.swap(b);
687 : }
688 :
689 : template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) noexcept
690 : {
691 : (void) static_cast< T* >( static_cast< U* >( 0 ) );
692 :
693 : typedef typename shared_ptr<T>::element_type E;
694 :
695 : E * p = static_cast< E* >( r.get() );
696 : return shared_ptr<T>( r, p );
697 : }
698 :
699 : template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) noexcept
700 : {
701 : (void) const_cast< T* >( static_cast< U* >( 0 ) );
702 :
703 : typedef typename shared_ptr<T>::element_type E;
704 :
705 : E * p = const_cast< E* >( r.get() );
706 : return shared_ptr<T>( r, p );
707 : }
708 :
709 : template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) noexcept
710 : {
711 : (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
712 :
713 : typedef typename shared_ptr<T>::element_type E;
714 :
715 : E * p = dynamic_cast< E* >( r.get() );
716 : return p? shared_ptr<T>( r, p ): shared_ptr<T>();
717 : }
718 :
719 : template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) noexcept
720 : {
721 : (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
722 :
723 : typedef typename shared_ptr<T>::element_type E;
724 :
725 : E * p = reinterpret_cast< E* >( r.get() );
726 : return shared_ptr<T>( r, p );
727 : }
728 :
729 : template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) noexcept
730 : {
731 : (void) static_cast< T* >( static_cast< U* >( 0 ) );
732 :
733 : typedef typename shared_ptr<T>::element_type E;
734 :
735 : E * p = static_cast< E* >( r.get() );
736 : return shared_ptr<T>( std::move(r), p );
737 : }
738 :
739 : template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) noexcept
740 : {
741 : (void) const_cast< T* >( static_cast< U* >( 0 ) );
742 :
743 : typedef typename shared_ptr<T>::element_type E;
744 :
745 : E * p = const_cast< E* >( r.get() );
746 : return shared_ptr<T>( std::move(r), p );
747 : }
748 :
749 : template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) noexcept
750 : {
751 : (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
752 :
753 : typedef typename shared_ptr<T>::element_type E;
754 :
755 : E * p = dynamic_cast< E* >( r.get() );
756 : return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>();
757 : }
758 :
759 : template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) noexcept
760 : {
761 : (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
762 :
763 : typedef typename shared_ptr<T>::element_type E;
764 :
765 : E * p = reinterpret_cast< E* >( r.get() );
766 : return shared_ptr<T>( std::move(r), p );
767 : }
768 :
769 : // get_pointer() enables boost::mem_fn to recognize shared_ptr
770 :
771 0 : template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) noexcept
772 : {
773 0 : return p.get();
774 : }
775 :
776 : // operator<<
777 :
778 : template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
779 : {
780 : os << p.get();
781 : return os;
782 : }
783 :
784 : // get_deleter
785 :
786 : namespace detail
787 : {
788 :
789 : template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) noexcept
790 : {
791 : return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID_(D)) );
792 : }
793 :
794 : template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) noexcept;
795 : template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) noexcept;
796 :
797 : class esft2_deleter_wrapper
798 : {
799 : private:
800 :
801 : shared_ptr<void const volatile> deleter_;
802 :
803 : public:
804 :
805 : esft2_deleter_wrapper() noexcept
806 : {
807 : }
808 :
809 : template< class T > void set_deleter( shared_ptr<T> const & deleter ) noexcept
810 : {
811 : deleter_ = deleter;
812 : }
813 :
814 : template<typename D> D* get_deleter() const noexcept
815 : {
816 : return boost::detail::basic_get_deleter<D>( deleter_ );
817 : }
818 :
819 : template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT
820 : {
821 : BOOST_ASSERT( deleter_.use_count() <= 1 );
822 : deleter_.reset();
823 : }
824 : };
825 :
826 : } // namespace detail
827 :
828 : template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) noexcept
829 : {
830 : D * d = boost::detail::basic_get_deleter<D>( p );
831 :
832 : if( d == 0 )
833 : {
834 : d = boost::detail::basic_get_local_deleter( d, p );
835 : }
836 :
837 : if( d == 0 )
838 : {
839 : boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
840 : // The following get_deleter method call is fully qualified because
841 : // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
842 : if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
843 : }
844 :
845 : return d;
846 : }
847 :
848 : // atomic access
849 :
850 : #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
851 :
852 : template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) noexcept
853 : {
854 : return false;
855 : }
856 :
857 : template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept
858 : {
859 : boost::detail::spinlock_pool<2>::scoped_lock lock( p );
860 : return *p;
861 : }
862 :
863 : template<class T, class M> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ M ) noexcept
864 : {
865 : return atomic_load( p );
866 : }
867 :
868 : template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept
869 : {
870 : boost::detail::spinlock_pool<2>::scoped_lock lock( p );
871 : p->swap( r );
872 : }
873 :
874 : template<class T, class M> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) noexcept
875 : {
876 : atomic_store( p, r ); // std::move( r )
877 : }
878 :
879 : template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept
880 : {
881 : boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
882 :
883 : sp.lock();
884 : p->swap( r );
885 : sp.unlock();
886 :
887 : return r; // return std::move( r )
888 : }
889 :
890 : template<class T, class M> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ M ) noexcept
891 : {
892 : return atomic_exchange( p, r ); // std::move( r )
893 : }
894 :
895 : template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept
896 : {
897 : boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
898 :
899 : sp.lock();
900 :
901 : if( p->_internal_equiv( *v ) )
902 : {
903 : p->swap( w );
904 :
905 : sp.unlock();
906 :
907 : return true;
908 : }
909 : else
910 : {
911 : shared_ptr<T> tmp( *p );
912 :
913 : sp.unlock();
914 :
915 : tmp.swap( *v );
916 : return false;
917 : }
918 : }
919 :
920 : 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 ) noexcept
921 : {
922 : return atomic_compare_exchange( p, v, w ); // std::move( w )
923 : }
924 :
925 : #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
926 :
927 : // hash_value
928 :
929 : template< class T > struct hash;
930 :
931 : template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) noexcept
932 : {
933 : return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() );
934 : }
935 :
936 : } // namespace boost
937 :
938 : // std::hash
939 :
940 : namespace std
941 : {
942 :
943 : template<class T> struct hash< ::boost::shared_ptr<T> >
944 : {
945 : std::size_t operator()( ::boost::shared_ptr<T> const & p ) const noexcept
946 : {
947 : return std::hash< typename ::boost::shared_ptr<T>::element_type* >()( p.get() );
948 : }
949 : };
950 :
951 : } // namespace std
952 :
953 : #include <boost/smart_ptr/detail/local_sp_deleter.hpp>
954 :
955 : namespace boost
956 : {
957 :
958 : namespace detail
959 : {
960 :
961 : template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) noexcept
962 : {
963 : return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
964 : }
965 :
966 : template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) noexcept
967 : {
968 : return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID_(local_sp_deleter<D>) ) );
969 : }
970 :
971 : } // namespace detail
972 :
973 : #if defined(__cpp_deduction_guides)
974 :
975 : template<class T> shared_ptr( weak_ptr<T> ) -> shared_ptr<T>;
976 : template<class T, class D> shared_ptr( std::unique_ptr<T, D> ) -> shared_ptr<T>;
977 :
978 : #endif
979 :
980 : } // namespace boost
981 :
982 : #if defined( BOOST_SP_DISABLE_DEPRECATED )
983 : #pragma GCC diagnostic pop
984 : #endif
985 :
986 : #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
|