CppCMS

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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 {};
51 struct polymorphic_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>
184 shared_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
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 {
210 pn = booster::detail::shared_count();
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();
227 pn = booster::detail::shared_count(r);
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();
235 pn = booster::detail::shared_count( r );
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>
264 typename booster::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
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 {
384 return shared_ptr<T>(r, booster::detail::static_cast_tag());
385 }
386
387 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
388 {
389 return shared_ptr<T>(r, booster::detail::const_cast_tag());
390 }
391
392 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
393 {
394 return shared_ptr<T>(r, booster::detail::dynamic_cast_tag());
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 {
401 return shared_ptr<T>(r, booster::detail::static_cast_tag());
402 }
403
404 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
405 {
406 return shared_ptr<T>(r, booster::detail::dynamic_cast_tag());
407 }
408
409 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
410 {
411 return shared_ptr<T>(r, booster::detail::polymorphic_cast_tag());
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
booster::detail::dynamic_cast_tag
Definition: shared_ptr.h:50
booster::detail::shared_count
Definition: shared_count.h:37
booster::detail::sp_empty
Definition: sp_convertible.h:32
booster::detail::polymorphic_cast_tag
Definition: shared_ptr.h:51
booster::shared_ptr
Definition: log.h:25
booster::detail::sp_enable_if_convertible
Definition: sp_convertible.h:47
booster::enable_shared_from_this2
Definition: shared_ptr.h:43
booster::detail::sp_enable_if_auto_ptr
Definition: shared_ptr.h:103
booster::weak_ptr
Definition: log.h:27
booster::detail::const_cast_tag
Definition: shared_ptr.h:49
booster::bad_cast
Same as std::bad_cast but records stack trace.
Definition: backtrace.h:151
booster::enable_shared_from_this
This class is borrowed from boost.
Definition: enable_shared_from_this.h:30
booster::detail::sp_nothrow_tag
Definition: shared_count.h:33
booster::detail::shared_ptr_traits
Definition: shared_ptr.h:53
booster
Booster library namespace. The library that implements Boost Like API in ABI backward compatible way...
Definition: application.h:23
booster::detail::static_cast_tag
Definition: shared_ptr.h:48