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