source: NonGTP/Boost/boost/serialization/detail/shared_ptr_132.hpp @ 857

Revision 857, 12.1 KB checked in by igarcia, 18 years ago (diff)
Line 
1#ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
2#define BOOST_SHARED_PTR_132_HPP_INCLUDED
3
4//
5//  shared_ptr.hpp
6//
7//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8//  Copyright (c) 2001, 2002, 2003 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 <boost/config.hpp>   // for broken compiler workarounds
18
19#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
20#include <boost/serializaition/detail/shared_ptr_nmt_132.hpp>
21#else
22
23#include <boost/assert.hpp>
24#include <boost/checked_delete.hpp>
25#include <boost/throw_exception.hpp>
26#include <boost/detail/workaround.hpp>
27
28#include <boost/serialization/access.hpp>
29#include <boost/serialization/detail/shared_count_132.hpp>
30
31#include <memory>               // for std::auto_ptr
32#include <algorithm>            // for std::swap
33#include <functional>           // for std::less
34#include <typeinfo>             // for std::bad_cast
35#include <iosfwd>               // for std::basic_ostream
36
37#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
38# pragma warning(push)
39# pragma warning(disable:4284) // odd return type for operator->
40#endif
41
42namespace boost_132 {
43
44#if !BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x560) )
45using namespace boost;
46#endif
47
48template<class T> class weak_ptr;
49template<class T> class enable_shared_from_this;
50
51namespace detail
52{
53
54struct static_cast_tag {};
55struct const_cast_tag {};
56struct dynamic_cast_tag {};
57struct polymorphic_cast_tag {};
58
59template<class T> struct shared_ptr_traits
60{
61    typedef T & reference;
62};
63
64template<> struct shared_ptr_traits<void>
65{
66    typedef void reference;
67};
68
69#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
70
71template<> struct shared_ptr_traits<void const>
72{
73    typedef void reference;
74};
75
76template<> struct shared_ptr_traits<void volatile>
77{
78    typedef void reference;
79};
80
81template<> struct shared_ptr_traits<void const volatile>
82{
83    typedef void reference;
84};
85
86#endif
87
88// enable_shared_from_this support
89
90template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, enable_shared_from_this<T> const * pe, Y const * px )
91{
92    if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
93}
94
95inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
96{
97}
98
99} // namespace detail
100
101
102//
103//  shared_ptr
104//
105//  An enhanced relative of scoped_ptr with reference counted copy semantics.
106//  The object pointed to is deleted when the last shared_ptr pointing to it
107//  is destroyed or reset.
108//
109
110template<class T> class shared_ptr
111{
112private:
113    // Borland 5.5.1 specific workaround
114    typedef shared_ptr<T> this_type;
115
116public:
117
118    typedef T element_type;
119    typedef T value_type;
120    typedef T * pointer;
121    typedef typename detail::shared_ptr_traits<T>::reference reference;
122
123    shared_ptr(): px(0), pn() // never throws in 1.30+
124    {
125    }
126
127#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x564) )
128    template<class Y>
129    explicit shared_ptr(Y * p): px(p), pn(p,boost::checked_deleter<Y>()) // Y must be complete
130#else
131    template<class Y>
132    explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete
133#endif
134    {
135        detail::sp_enable_shared_from_this( pn, p, p );
136    }
137
138    //
139    // Requirements: D's copy constructor must not throw
140    //
141    // shared_ptr will release p by calling d(p)
142    //
143
144    template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
145    {
146        detail::sp_enable_shared_from_this( pn, p, p );
147    }
148
149//  generated copy constructor, assignment, destructor are fine...
150
151//  except that Borland C++ has a bug, and g++ with -Wsynth warns
152#if defined(__BORLANDC__) || defined(__GNUC__)
153
154    shared_ptr & operator=(shared_ptr const & r) // never throws
155    {
156        px = r.px;
157        pn = r.pn; // shared_count::op= doesn't throw
158        return *this;
159    }
160
161#endif
162
163    template<class Y>
164    explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
165    {
166        // it is now safe to copy r.px, as pn(r.pn) did not throw
167        px = r.px;
168    }
169
170    template<class Y>
171    shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
172    {
173    }
174
175    template<class Y>
176    shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
177    {
178    }
179
180    template<class Y>
181    shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
182    {
183    }
184
185    template<class Y>
186    shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
187    {
188        if(px == 0) // need to allocate new counter -- the cast failed
189        {
190            pn = detail::shared_count();
191        }
192    }
193
194    template<class Y>
195    shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
196    {
197        if(px == 0)
198        {
199            boost::throw_exception(std::bad_cast());
200        }
201    }
202
203#ifndef BOOST_NO_AUTO_PTR
204
205    template<class Y>
206    explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
207    {
208        Y * tmp = r.get();
209        pn = detail::shared_count(r);
210        detail::sp_enable_shared_from_this( pn, tmp, tmp );
211    }
212
213#endif
214
215#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
216
217    template<class Y>
218    shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
219    {
220        px = r.px;
221        pn = r.pn; // shared_count::op= doesn't throw
222        return *this;
223    }
224
225#endif
226
227#ifndef BOOST_NO_AUTO_PTR
228
229    template<class Y>
230    shared_ptr & operator=(std::auto_ptr<Y> & r)
231    {
232        this_type(r).swap(*this);
233        return *this;
234    }
235
236#endif
237
238    void reset() // never throws in 1.30+
239    {
240        this_type().swap(*this);
241    }
242
243    template<class Y> void reset(Y * p) // Y must be complete
244    {
245        BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
246        this_type(p).swap(*this);
247    }
248
249    template<class Y, class D> void reset(Y * p, D d)
250    {
251        this_type(p, d).swap(*this);
252    }
253
254    reference operator* () const // never throws
255    {
256        BOOST_ASSERT(px != 0);
257        return *px;
258    }
259
260    T * operator-> () const // never throws
261    {
262        BOOST_ASSERT(px != 0);
263        return px;
264    }
265   
266    T * get() const // never throws
267    {
268        return px;
269    }
270
271    // implicit conversion to "bool"
272
273#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
274
275    operator bool () const
276    {
277        return px != 0;
278    }
279
280#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
281    typedef T * (this_type::*unspecified_bool_type)() const;
282   
283    operator unspecified_bool_type() const // never throws
284    {
285        return px == 0? 0: &this_type::get;
286    }
287
288#else
289
290    typedef T * this_type::*unspecified_bool_type;
291
292    operator unspecified_bool_type() const // never throws
293    {
294        return px == 0? 0: &this_type::px;
295    }
296
297#endif
298
299    // operator! is redundant, but some compilers need it
300
301    bool operator! () const // never throws
302    {
303        return px == 0;
304    }
305
306    bool unique() const // never throws
307    {
308        return pn.unique();
309    }
310
311    long use_count() const // never throws
312    {
313        return pn.use_count();
314    }
315
316    void swap(shared_ptr<T> & other) // never throws
317    {
318        std::swap(px, other.px);
319        pn.swap(other.pn);
320    }
321
322    template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
323    {
324        return pn < rhs.pn;
325    }
326
327    void * _internal_get_deleter(std::type_info const & ti) const
328    {
329        return pn.get_deleter(ti);
330    }
331
332// Tasteless as this may seem, making all members public allows member templates
333// to work in the absence of member template friends. (Matthew Langston)
334
335#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
336
337private:
338
339    template<class Y> friend class shared_ptr;
340    template<class Y> friend class weak_ptr;
341
342
343#endif
344public: // for serialization
345    T * px;                     // contained pointer
346    detail::shared_count pn;    // reference counter
347
348};  // shared_ptr
349
350template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
351{
352    return a.get() == b.get();
353}
354
355template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
356{
357    return a.get() != b.get();
358}
359
360#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
361
362// Resolve the ambiguity between our op!= and the one in rel_ops
363
364template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
365{
366    return a.get() != b.get();
367}
368
369#endif
370
371template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
372{
373    return a._internal_less(b);
374}
375
376template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
377{
378    a.swap(b);
379}
380
381template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
382{
383    return shared_ptr<T>(r, detail::static_cast_tag());
384}
385
386template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
387{
388    return shared_ptr<T>(r, detail::const_cast_tag());
389}
390
391template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
392{
393    return shared_ptr<T>(r, detail::dynamic_cast_tag());
394}
395
396// shared_*_cast names are deprecated. Use *_pointer_cast instead.
397
398template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
399{
400    return shared_ptr<T>(r, detail::static_cast_tag());
401}
402
403template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
404{
405    return shared_ptr<T>(r, detail::dynamic_cast_tag());
406}
407
408template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
409{
410    return shared_ptr<T>(r, detail::polymorphic_cast_tag());
411}
412
413template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
414{
415    BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
416    return shared_static_cast<T>(r);
417}
418
419// get_pointer() enables boost::mem_fn to recognize shared_ptr
420
421template<class T> inline T * get_pointer(shared_ptr<T> const & p)
422{
423    return p.get();
424}
425
426// operator<<
427
428#if defined(__GNUC__) &&  (__GNUC__ < 3)
429
430template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
431{
432    os << p.get();
433    return os;
434}
435
436#else
437
438# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
439// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
440using std::basic_ostream;
441template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
442# else
443template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
444# endif
445{
446    os << p.get();
447    return os;
448}
449
450#endif
451
452// get_deleter (experimental)
453
454#if (defined(__GNUC__) &&  (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238))
455
456// g++ 2.9x doesn't allow static_cast<X const *>(void *)
457// apparently EDG 2.38 also doesn't accept it
458
459template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
460{
461    void const * q = p._internal_get_deleter(typeid(D));
462    return const_cast<D *>(static_cast<D const *>(q));
463}
464
465#else
466
467template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
468{
469    return static_cast<D *>(p._internal_get_deleter(typeid(D)));
470}
471
472#endif
473
474} // namespace boost
475
476#ifdef BOOST_MSVC
477# pragma warning(pop)
478#endif   
479
480#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
481
482#endif  // #ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.