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