Line data Source code
1 : #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
2 : #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
3 :
4 : // MS compatible compilers support #pragma once
5 :
6 : #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 : # pragma once
8 : #endif
9 :
10 : //
11 : // detail/shared_count.hpp
12 : //
13 : // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
14 : // Copyright 2004-2005 Peter Dimov
15 : //
16 : // Distributed under the Boost Software License, Version 1.0. (See
17 : // accompanying file LICENSE_1_0.txt or copy at
18 : // http://www.boost.org/LICENSE_1_0.txt)
19 : //
20 :
21 : #ifdef __BORLANDC__
22 : # pragma warn -8027 // Functions containing try are not expanded inline
23 : #endif
24 :
25 : #include <boost/config.hpp>
26 : #include <boost/checked_delete.hpp>
27 : #include <boost/throw_exception.hpp>
28 : #include <boost/smart_ptr/bad_weak_ptr.hpp>
29 : #include <boost/smart_ptr/detail/sp_counted_base.hpp>
30 : #include <boost/smart_ptr/detail/sp_counted_impl.hpp>
31 : #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
32 : #include <boost/smart_ptr/detail/sp_noexcept.hpp>
33 : #include <boost/config/workaround.hpp>
34 : // In order to avoid circular dependencies with Boost.TR1
35 : // we make sure that our include of <memory> doesn't try to
36 : // pull in the TR1 headers: that's why we use this header
37 : // rather than including <memory> directly:
38 : #include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
39 : #include <functional> // std::less
40 :
41 : #ifdef BOOST_NO_EXCEPTIONS
42 : # include <new> // std::bad_alloc
43 : #endif
44 :
45 : #include <boost/core/addressof.hpp>
46 :
47 : #if defined( BOOST_SP_DISABLE_DEPRECATED )
48 : #pragma GCC diagnostic push
49 : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
50 : #endif
51 :
52 : namespace boost
53 : {
54 :
55 : namespace movelib
56 : {
57 :
58 : template< class T, class D > class unique_ptr;
59 :
60 : } // namespace movelib
61 :
62 : namespace detail
63 : {
64 :
65 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
66 :
67 : int const shared_count_id = 0x2C35F101;
68 : int const weak_count_id = 0x298C38A4;
69 :
70 : #endif
71 :
72 : struct sp_nothrow_tag {};
73 :
74 : template< class D > struct sp_inplace_tag
75 : {
76 : };
77 :
78 : template< class T > class sp_reference_wrapper
79 : {
80 : public:
81 :
82 : explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
83 : {
84 : }
85 :
86 : template< class Y > void operator()( Y * p ) const
87 : {
88 : (*t_)( p );
89 : }
90 :
91 : private:
92 :
93 : T * t_;
94 : };
95 :
96 : template< class D > struct sp_convert_reference
97 : {
98 : typedef D type;
99 : };
100 :
101 : template< class D > struct sp_convert_reference< D& >
102 : {
103 : typedef sp_reference_wrapper< D > type;
104 : };
105 :
106 : class weak_count;
107 :
108 : class shared_count
109 : {
110 : private:
111 :
112 : sp_counted_base * pi_;
113 :
114 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
115 : int id_;
116 : #endif
117 :
118 : friend class weak_count;
119 :
120 : public:
121 :
122 0 : BOOST_CONSTEXPR shared_count() BOOST_SP_NOEXCEPT: pi_(0)
123 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
124 : , id_(shared_count_id)
125 : #endif
126 : {
127 : }
128 :
129 : BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPT: pi_( pi )
130 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
131 : , id_(shared_count_id)
132 : #endif
133 : {
134 : }
135 :
136 0 : template<class Y> explicit shared_count( Y * p ): pi_( 0 )
137 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
138 : , id_(shared_count_id)
139 : #endif
140 : {
141 : #ifndef BOOST_NO_EXCEPTIONS
142 :
143 : try
144 : {
145 0 : pi_ = new sp_counted_impl_p<Y>( p );
146 : }
147 0 : catch(...)
148 : {
149 0 : boost::checked_delete( p );
150 0 : throw;
151 : }
152 :
153 : #else
154 :
155 : pi_ = new sp_counted_impl_p<Y>( p );
156 :
157 : if( pi_ == 0 )
158 : {
159 : boost::checked_delete( p );
160 : boost::throw_exception( std::bad_alloc() );
161 : }
162 :
163 : #endif
164 0 : }
165 :
166 : #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
167 : template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
168 : #else
169 0 : template<class P, class D> shared_count( P p, D d ): pi_(0)
170 : #endif
171 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
172 : , id_(shared_count_id)
173 : #endif
174 : {
175 : #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
176 : typedef Y* P;
177 : #endif
178 : #ifndef BOOST_NO_EXCEPTIONS
179 :
180 : try
181 : {
182 0 : pi_ = new sp_counted_impl_pd<P, D>(p, d);
183 : }
184 0 : catch(...)
185 : {
186 0 : d(p); // delete p
187 0 : throw;
188 : }
189 :
190 : #else
191 :
192 : pi_ = new sp_counted_impl_pd<P, D>(p, d);
193 :
194 : if(pi_ == 0)
195 : {
196 : d(p); // delete p
197 : boost::throw_exception(std::bad_alloc());
198 : }
199 :
200 : #endif
201 0 : }
202 :
203 : #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
204 :
205 : template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
206 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
207 : , id_(shared_count_id)
208 : #endif
209 : {
210 : #ifndef BOOST_NO_EXCEPTIONS
211 :
212 : try
213 : {
214 : pi_ = new sp_counted_impl_pd< P, D >( p );
215 : }
216 : catch( ... )
217 : {
218 : D::operator_fn( p ); // delete p
219 : throw;
220 : }
221 :
222 : #else
223 :
224 : pi_ = new sp_counted_impl_pd< P, D >( p );
225 :
226 : if( pi_ == 0 )
227 : {
228 : D::operator_fn( p ); // delete p
229 : boost::throw_exception( std::bad_alloc() );
230 : }
231 :
232 : #endif // #ifndef BOOST_NO_EXCEPTIONS
233 : }
234 :
235 : #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
236 :
237 : template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
238 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
239 : , id_(shared_count_id)
240 : #endif
241 : {
242 : typedef sp_counted_impl_pda<P, D, A> impl_type;
243 :
244 : #if !defined( BOOST_NO_CXX11_ALLOCATOR )
245 :
246 : typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
247 :
248 : #else
249 :
250 : typedef typename A::template rebind< impl_type >::other A2;
251 :
252 : #endif
253 :
254 : A2 a2( a );
255 :
256 : #ifndef BOOST_NO_EXCEPTIONS
257 :
258 : try
259 : {
260 : pi_ = a2.allocate( 1 );
261 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
262 : }
263 : catch(...)
264 : {
265 : d( p );
266 :
267 : if( pi_ != 0 )
268 : {
269 : a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
270 : }
271 :
272 : throw;
273 : }
274 :
275 : #else
276 :
277 : pi_ = a2.allocate( 1 );
278 :
279 : if( pi_ != 0 )
280 : {
281 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
282 : }
283 : else
284 : {
285 : d( p );
286 : boost::throw_exception( std::bad_alloc() );
287 : }
288 :
289 : #endif
290 : }
291 :
292 : #if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
293 :
294 : template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
295 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
296 : , id_(shared_count_id)
297 : #endif
298 : {
299 : typedef sp_counted_impl_pda< P, D, A > impl_type;
300 :
301 : #if !defined( BOOST_NO_CXX11_ALLOCATOR )
302 :
303 : typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
304 :
305 : #else
306 :
307 : typedef typename A::template rebind< impl_type >::other A2;
308 :
309 : #endif
310 :
311 : A2 a2( a );
312 :
313 : #ifndef BOOST_NO_EXCEPTIONS
314 :
315 : try
316 : {
317 : pi_ = a2.allocate( 1 );
318 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
319 : }
320 : catch(...)
321 : {
322 : D::operator_fn( p );
323 :
324 : if( pi_ != 0 )
325 : {
326 : a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
327 : }
328 :
329 : throw;
330 : }
331 :
332 : #else
333 :
334 : pi_ = a2.allocate( 1 );
335 :
336 : if( pi_ != 0 )
337 : {
338 : ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
339 : }
340 : else
341 : {
342 : D::operator_fn( p );
343 : boost::throw_exception( std::bad_alloc() );
344 : }
345 :
346 : #endif // #ifndef BOOST_NO_EXCEPTIONS
347 : }
348 :
349 : #endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
350 :
351 : #ifndef BOOST_NO_AUTO_PTR
352 :
353 : // auto_ptr<Y> is special cased to provide the strong guarantee
354 :
355 : template<class Y>
356 : explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
357 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
358 : , id_(shared_count_id)
359 : #endif
360 : {
361 : #ifdef BOOST_NO_EXCEPTIONS
362 :
363 : if( pi_ == 0 )
364 : {
365 : boost::throw_exception(std::bad_alloc());
366 : }
367 :
368 : #endif
369 :
370 : r.release();
371 : }
372 :
373 : #endif
374 :
375 : #if !defined( BOOST_NO_CXX11_SMART_PTR )
376 :
377 : template<class Y, class D>
378 : explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
379 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
380 : , id_(shared_count_id)
381 : #endif
382 : {
383 : typedef typename sp_convert_reference<D>::type D2;
384 :
385 : D2 d2( r.get_deleter() );
386 : pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
387 :
388 : #ifdef BOOST_NO_EXCEPTIONS
389 :
390 : if( pi_ == 0 )
391 : {
392 : boost::throw_exception( std::bad_alloc() );
393 : }
394 :
395 : #endif
396 :
397 : r.release();
398 : }
399 :
400 : #endif
401 :
402 : template<class Y, class D>
403 : explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
404 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
405 : , id_(shared_count_id)
406 : #endif
407 : {
408 : typedef typename sp_convert_reference<D>::type D2;
409 :
410 : D2 d2( r.get_deleter() );
411 : pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
412 :
413 : #ifdef BOOST_NO_EXCEPTIONS
414 :
415 : if( pi_ == 0 )
416 : {
417 : boost::throw_exception( std::bad_alloc() );
418 : }
419 :
420 : #endif
421 :
422 : r.release();
423 : }
424 :
425 0 : ~shared_count() /*BOOST_SP_NOEXCEPT*/
426 0 : {
427 0 : if( pi_ != 0 ) pi_->release();
428 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
429 : id_ = 0;
430 : #endif
431 : }
432 :
433 0 : shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
434 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
435 : , id_(shared_count_id)
436 : #endif
437 : {
438 0 : if( pi_ != 0 ) pi_->add_ref_copy();
439 : }
440 :
441 : #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
442 :
443 : shared_count(shared_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
444 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
445 : , id_(shared_count_id)
446 : #endif
447 : {
448 : r.pi_ = 0;
449 : }
450 :
451 : #endif
452 :
453 : explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
454 : shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT; // constructs an empty *this when r.use_count() == 0
455 :
456 : shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
457 : {
458 : sp_counted_base * tmp = r.pi_;
459 :
460 : if( tmp != pi_ )
461 : {
462 : if( tmp != 0 ) tmp->add_ref_copy();
463 : if( pi_ != 0 ) pi_->release();
464 : pi_ = tmp;
465 : }
466 :
467 : return *this;
468 : }
469 :
470 0 : void swap(shared_count & r) BOOST_SP_NOEXCEPT
471 : {
472 0 : sp_counted_base * tmp = r.pi_;
473 0 : r.pi_ = pi_;
474 0 : pi_ = tmp;
475 : }
476 :
477 0 : long use_count() const BOOST_SP_NOEXCEPT
478 : {
479 0 : return pi_ != 0? pi_->use_count(): 0;
480 : }
481 :
482 0 : bool unique() const BOOST_SP_NOEXCEPT
483 : {
484 0 : return use_count() == 1;
485 : }
486 :
487 0 : bool empty() const BOOST_SP_NOEXCEPT
488 : {
489 0 : return pi_ == 0;
490 : }
491 :
492 : friend inline bool operator==(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
493 : {
494 : return a.pi_ == b.pi_;
495 : }
496 :
497 0 : friend inline bool operator<(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
498 : {
499 0 : return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
500 : }
501 :
502 : void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
503 : {
504 : return pi_? pi_->get_deleter( ti ): 0;
505 : }
506 :
507 : void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
508 : {
509 : return pi_? pi_->get_local_deleter( ti ): 0;
510 : }
511 :
512 : void * get_untyped_deleter() const BOOST_SP_NOEXCEPT
513 : {
514 : return pi_? pi_->get_untyped_deleter(): 0;
515 : }
516 : };
517 :
518 :
519 : class weak_count
520 : {
521 : private:
522 :
523 : sp_counted_base * pi_;
524 :
525 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
526 : int id_;
527 : #endif
528 :
529 : friend class shared_count;
530 :
531 : public:
532 :
533 0 : BOOST_CONSTEXPR weak_count() BOOST_SP_NOEXCEPT: pi_(0)
534 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
535 : , id_(weak_count_id)
536 : #endif
537 : {
538 : }
539 :
540 : weak_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
541 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
542 : , id_(weak_count_id)
543 : #endif
544 : {
545 : if(pi_ != 0) pi_->weak_add_ref();
546 : }
547 :
548 : weak_count(weak_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
549 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
550 : , id_(weak_count_id)
551 : #endif
552 : {
553 : if(pi_ != 0) pi_->weak_add_ref();
554 : }
555 :
556 : // Move support
557 :
558 : #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
559 :
560 : weak_count(weak_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
561 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
562 : , id_(weak_count_id)
563 : #endif
564 : {
565 : r.pi_ = 0;
566 : }
567 :
568 : #endif
569 :
570 0 : ~weak_count() /*BOOST_SP_NOEXCEPT*/
571 : {
572 0 : if(pi_ != 0) pi_->weak_release();
573 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
574 : id_ = 0;
575 : #endif
576 : }
577 :
578 : weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
579 : {
580 : sp_counted_base * tmp = r.pi_;
581 :
582 : if( tmp != pi_ )
583 : {
584 : if(tmp != 0) tmp->weak_add_ref();
585 : if(pi_ != 0) pi_->weak_release();
586 : pi_ = tmp;
587 : }
588 :
589 : return *this;
590 : }
591 :
592 : weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPT
593 : {
594 : sp_counted_base * tmp = r.pi_;
595 :
596 : if( tmp != pi_ )
597 : {
598 : if(tmp != 0) tmp->weak_add_ref();
599 : if(pi_ != 0) pi_->weak_release();
600 : pi_ = tmp;
601 : }
602 :
603 : return *this;
604 : }
605 :
606 : void swap(weak_count & r) BOOST_SP_NOEXCEPT
607 : {
608 : sp_counted_base * tmp = r.pi_;
609 : r.pi_ = pi_;
610 : pi_ = tmp;
611 : }
612 :
613 0 : long use_count() const BOOST_SP_NOEXCEPT
614 : {
615 0 : return pi_ != 0? pi_->use_count(): 0;
616 : }
617 :
618 : bool empty() const BOOST_SP_NOEXCEPT
619 : {
620 : return pi_ == 0;
621 : }
622 :
623 : friend inline bool operator==(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
624 : {
625 : return a.pi_ == b.pi_;
626 : }
627 :
628 : friend inline bool operator<(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
629 : {
630 : return std::less<sp_counted_base *>()(a.pi_, b.pi_);
631 : }
632 : };
633 :
634 : inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
635 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
636 : , id_(shared_count_id)
637 : #endif
638 : {
639 : if( pi_ == 0 || !pi_->add_ref_lock() )
640 : {
641 : boost::throw_exception( boost::bad_weak_ptr() );
642 : }
643 : }
644 :
645 0 : inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT: pi_( r.pi_ )
646 : #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
647 : , id_(shared_count_id)
648 : #endif
649 : {
650 0 : if( pi_ != 0 && !pi_->add_ref_lock() )
651 : {
652 0 : pi_ = 0;
653 : }
654 0 : }
655 :
656 : } // namespace detail
657 :
658 : } // namespace boost
659 :
660 : #if defined( BOOST_SP_DISABLE_DEPRECATED )
661 : #pragma GCC diagnostic pop
662 : #endif
663 :
664 : #ifdef __BORLANDC__
665 : # pragma warn .8027 // Functions containing try are not expanded inline
666 : #endif
667 :
668 : #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
|