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