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