CppCMS
shared_ptr.h
1 #ifndef BOOSTER_SMART_PTR_SHARED_PTR_HPP_INCLUDED
2 #define BOOSTER_SMART_PTR_SHARED_PTR_HPP_INCLUDED
3 
4 //
5 // shared_ptr.hpp
6 //
7 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 // Copyright (c) 2001-2008 Peter Dimov
9 //
10 // Distributed under the Boost Software License, Version 1.0. (See
11 // accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 //
14 // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
15 //
16 
17 #include <booster/config.h> // for broken compiler workarounds
18 
19 #include <booster/auto_ptr_inc.h>
20 #include <cassert>
21 #include <booster/backtrace.h>
22 #include <booster/checked_delete.h>
23 #include <booster/smart_ptr/shared_count.h>
24 #include <booster/smart_ptr/sp_convertible.h>
25 
26 #include <algorithm> // for std::swap
27 #include <functional> // for std::less
28 #include <typeinfo> // for std::bad_cast
29 
30 #include <iosfwd> // for std::basic_ostream
31 
32 #ifdef BOOSTER_MSVC // moved here to work around VC++ compiler crash
33 # pragma warning(push)
34 # pragma warning(disable:4284) // odd return type for operator->
35 #endif
36 
37 namespace booster
38 {
39 
40 template<class T> class shared_ptr;
41 template<class T> class weak_ptr;
42 template<class T> class enable_shared_from_this;
43 template<class T> class enable_shared_from_this2;
44 
45 namespace detail
46 {
47 
48 struct static_cast_tag {};
49 struct const_cast_tag {};
50 struct dynamic_cast_tag {};
52 
53 template<class T> struct shared_ptr_traits
54 {
55  typedef T & reference;
56 };
57 
58 template<> struct shared_ptr_traits<void>
59 {
60  typedef void reference;
61 };
62 
63 template<> struct shared_ptr_traits<void const>
64 {
65  typedef void reference;
66 };
67 
68 template<> struct shared_ptr_traits<void volatile>
69 {
70  typedef void reference;
71 };
72 
73 template<> struct shared_ptr_traits<void const volatile>
74 {
75  typedef void reference;
76 };
77 
78 // enable_shared_from_this support
79 
80 template< class X, class Y, class T > inline void sp_enable_shared_from_this( booster::shared_ptr<X> const * ppx, Y const * py, booster::enable_shared_from_this< T > const * pe )
81 {
82  if( pe != 0 )
83  {
84  pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
85  }
86 }
87 
88 template< class X, class Y, class T > inline void sp_enable_shared_from_this( booster::shared_ptr<X> * ppx, Y const * py, booster::enable_shared_from_this2< T > const * pe )
89 {
90  if( pe != 0 )
91  {
92  pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
93  }
94 }
95 
96 inline void sp_enable_shared_from_this( ... )
97 {
98 }
99 
100 
101 // rvalue auto_ptr support based on a technique by Dave Abrahams
102 
103 template< class T, class R > struct sp_enable_if_auto_ptr
104 {
105 };
106 
107 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
108 {
109  typedef R type;
110 };
111 
112 } // namespace detail
113 
114 
115 //
116 // shared_ptr
117 //
118 // An enhanced relative of scoped_ptr with reference counted copy semantics.
119 // The object pointed to is deleted when the last shared_ptr pointing to it
120 // is destroyed or reset.
121 //
122 
123 template<class T> class shared_ptr
124 {
125 private:
126 
127  // Borland 5.5.1 specific workaround
128  typedef shared_ptr<T> this_type;
129 
130 public:
131 
132  typedef T element_type;
133  typedef T value_type;
134  typedef T * pointer;
135  typedef typename booster::detail::shared_ptr_traits<T>::reference reference;
136 
137  shared_ptr(): px(0), pn() // never throws in 1.30+
138  {
139  }
140 
141  template<class Y>
142  explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
143  {
144  booster::detail::sp_enable_shared_from_this( this, p, p );
145  }
146 
147  //
148  // Requirements: D's copy constructor must not throw
149  //
150  // shared_ptr will release p by calling d(p)
151  //
152 
153  template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
154  {
155  booster::detail::sp_enable_shared_from_this( this, p, p );
156  }
157 
158  // As above, but with allocator. A's copy constructor shall not throw.
159 
160  template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
161  {
162  booster::detail::sp_enable_shared_from_this( this, p, p );
163  }
164 
165 // generated copy constructor, destructor are fine
166 
167  template<class Y>
168  explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
169  {
170  // it is now safe to copy r.px, as pn(r.pn) did not throw
171  px = r.px;
172  }
173 
174  template<class Y>
175  shared_ptr( weak_ptr<Y> const & r, booster::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, booster::detail::sp_nothrow_tag() ) // never throws
176  {
177  if( !pn.empty() )
178  {
179  px = r.px;
180  }
181  }
182 
183  template<class Y>
185  : px( r.px ), pn( r.pn ) // never throws
186  {
187  }
188 
189  // aliasing
190  template< class Y >
191  shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
192  {
193  }
194 
195  template<class Y>
196  shared_ptr(shared_ptr<Y> const & r, booster::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
197  {
198  }
199 
200  template<class Y>
201  shared_ptr(shared_ptr<Y> const & r, booster::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
202  {
203  }
204 
205  template<class Y>
206  shared_ptr(shared_ptr<Y> const & r, booster::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
207  {
208  if(px == 0) // need to allocate new counter -- the cast failed
209  {
211  }
212  }
213 
214  template<class Y>
215  shared_ptr(shared_ptr<Y> const & r, booster::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
216  {
217  if(px == 0)
218  {
219  throw booster::bad_cast();
220  }
221  }
222 
223  template<class Y>
224  explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
225  {
226  Y * tmp = r.get();
228  booster::detail::sp_enable_shared_from_this( this, tmp, tmp );
229  }
230 
231  template<class Ap>
232  explicit shared_ptr( Ap r, typename booster::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
233  {
234  typename Ap::element_type * tmp = r.get();
236  booster::detail::sp_enable_shared_from_this( this, tmp, tmp );
237  }
238 
239 
240  // assignment
241 
242  shared_ptr & operator=( shared_ptr const & r ) // never throws
243  {
244  this_type(r).swap(*this);
245  return *this;
246  }
247 
248  template<class Y>
249  shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
250  {
251  this_type(r).swap(*this);
252  return *this;
253  }
254 
255 
256  template<class Y>
257  shared_ptr & operator=( std::auto_ptr<Y> & r )
258  {
259  this_type(r).swap(*this);
260  return *this;
261  }
262 
263  template<class Ap>
265  {
266  this_type( r ).swap( *this );
267  return *this;
268  }
269 
270 // Move support
271 
272  void reset() // never throws in 1.30+
273  {
274  this_type().swap(*this);
275  }
276 
277  template<class Y> void reset(Y * p) // Y must be complete
278  {
279  assert(p == 0 || p != px); // catch self-reset errors
280  this_type(p).swap(*this);
281  }
282 
283  template<class Y, class D> void reset( Y * p, D d )
284  {
285  this_type( p, d ).swap( *this );
286  }
287 
288  template<class Y, class D, class A> void reset( Y * p, D d, A a )
289  {
290  this_type( p, d, a ).swap( *this );
291  }
292 
293  template<class Y> void reset( shared_ptr<Y> const & r, T * p )
294  {
295  this_type( r, p ).swap( *this );
296  }
297 
298  reference operator* () const // never throws
299  {
300  assert(px != 0);
301  return *px;
302  }
303 
304  T * operator-> () const // never throws
305  {
306  assert(px != 0);
307  return px;
308  }
309 
310  T * get() const // never throws
311  {
312  return px;
313  }
314 
315 // implicit conversion to "bool"
316 #include <booster/smart_ptr/operator_bool.h>
317 
318  bool unique() const // never throws
319  {
320  return pn.unique();
321  }
322 
323  long use_count() const // never throws
324  {
325  return pn.use_count();
326  }
327 
328  void swap(shared_ptr<T> & other) // never throws
329  {
330  std::swap(px, other.px);
331  pn.swap(other.pn);
332  }
333 
334  template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
335  {
336  return pn < rhs.pn;
337  }
338 
339  void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
340  {
341  return pn.get_deleter( ti );
342  }
343 
344  bool _internal_equiv( shared_ptr const & r ) const
345  {
346  return px == r.px && pn == r.pn;
347  }
348 
349 // Tasteless as this may seem, making all members public allows member templates
350 // to work in the absence of member template friends. (Matthew Langston)
351 
352 private:
353 
354  template<class Y> friend class shared_ptr;
355  template<class Y> friend class weak_ptr;
356 
357  T * px; // contained pointer
358  booster::detail::shared_count pn; // reference counter
359 
360 }; // shared_ptr
361 
362 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
363 {
364  return a.get() == b.get();
365 }
366 
367 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
368 {
369  return a.get() != b.get();
370 }
371 
372 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
373 {
374  return a._internal_less(b);
375 }
376 
377 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
378 {
379  a.swap(b);
380 }
381 
382 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
383 {
385 }
386 
387 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
388 {
390 }
391 
392 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
393 {
395 }
396 
397 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
398 
399 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
400 {
402 }
403 
404 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
405 {
407 }
408 
409 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
410 {
412 }
413 
414 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
415 {
416  assert(dynamic_cast<T *>(r.get()) == r.get());
417  return shared_static_cast<T>(r);
418 }
419 
420 // get_pointer() enables boost::mem_fn to recognize shared_ptr
421 
422 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
423 {
424  return p.get();
425 }
426 
427 // operator<<
428 
429 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
430 {
431  os << p.get();
432  return os;
433 }
434 
435 // get_deleter
436 
437 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
438 {
439  return static_cast<D *>(p._internal_get_deleter(BOOSTER_SP_TYPEID(D)));
440 }
441 
442 } // namespace boost
443 
444 #ifdef BOOSTER_MSVC
445 # pragma warning(pop)
446 #endif
447 
448 #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
Definition: shared_ptr.h:50
Definition: shared_count.h:37
Definition: sp_convertible.h:32
Definition: shared_ptr.h:51
Definition: log.h:25
Definition: sp_convertible.h:47
Definition: shared_ptr.h:43
Definition: shared_ptr.h:103
Definition: log.h:27
Definition: shared_ptr.h:49
Same as std::bad_cast but records stack trace.
Definition: backtrace.h:151
This class is borrowed from boost.
Definition: enable_shared_from_this.h:30
Definition: shared_count.h:33
Definition: shared_ptr.h:53
Booster library namespace. The library that implements Boost Like API in ABI backward compatible way...
Definition: application.h:23
Definition: shared_ptr.h:48