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