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