root/library/bdm/shared_ptr.h @ 1064

Revision 1064, 7.4 kB (checked in by mido, 14 years ago)

astyle applied all over the library

  • Property svn:eol-style set to native
RevLine 
[419]1/*!
2  \file
[529]3  \brief BDM's own smart pointers.
[419]4  \author Vaclav Barta.
5
6  -----------------------------------
7  BDM++ - C++ library for Bayesian Decision Making under Uncertainty
8
9  Using IT++ for numerical operations
10  -----------------------------------
11*/
12
13#ifndef shared_ptr_h
14#define shared_ptr_h
15
16#include <limits.h>
17#include <algorithm>
18#include <stdexcept>
19#include <string>
[565]20#include "bdmerror.h"
[419]21
22namespace bdm {
23
[555]24/*! \brief A naive implementation of roughly a subset of the std::tr1::shared_ptr spec
[529]25
26  Really just roughly - it ignores memory
27  exceptions, for example; also note I didn't read the spec.
28
[555]29  The standard template would naturally be preferable, \b if it was
[529]30  included in the standard libraries of all supported compilers - but
31  as of 2009, that's still a problem...
32*/
[419]33template <typename T>
34class shared_ptr {
[1064]35    template<class U> friend class shared_ptr;
[461]36
[419]37private:
[1064]38    T *payload;
39    unsigned *refCnt;
[419]40
41public:
[1064]42    /*!
43      \brief Default constructor
[555]44
[1064]45      Creates an empty shared_ptr - one that doesn't point anywhere.
46    */
47    shared_ptr() :
48        payload ( 0 ),
49        refCnt ( 0 ) {
50    }
[419]51
[1064]52    /*!
53      Constructs a shared_ptr that owns the pointer p (unless p
54      is NULL, in which case this constructor creates an empty
55      shared_ptr). When p isn't null, it must have been alllocated
56      by new!
57    */
58    shared_ptr ( T *p ) :
59        payload ( p ),
60        refCnt ( p ? new unsigned ( 1 ) : 0 ) {
61    }
[419]62
[1064]63    /*!
64      \brief Copy constructor
[555]65
[1064]66      If other is empty, constructs an empty shared_ptr; otherwise,
67      constructs a shared_ptr that shares ownership with other.
68    */
69    shared_ptr ( const shared_ptr<T> &other ) :
70        payload ( other.payload ),
71        refCnt ( other.refCnt ) {
72        add_ref();
73    }
[419]74
[1064]75    /*!
76      \brief Generalized copy
[555]77
[1064]78      Allows initialization of shared pointer of a base type from
79      raw pointer to a derived type.
[555]80
[1064]81      If other is empty, constructs an empty shared_ptr; otherwise,
82      constructs a shared_ptr that shares ownership with other.
83    */
84    template<typename U>
85    shared_ptr ( const shared_ptr<U> &other ) :
86        payload ( other.payload ),
87        refCnt ( other.refCnt ) {
88        add_ref();
89    }
[419]90
[1064]91    /*!
92      Destructor.
93    */
94    ~shared_ptr() {
95        del_ref();
96    }
[419]97
[1064]98    /*!
99      \brief Assignment operator
100    */
101    shared_ptr<T> &operator= ( const shared_ptr<T> &other ) {
102        other.add_ref();
103        del_ref();
[419]104
[1064]105        payload = other.payload;
106        refCnt = other.refCnt;
[419]107
[1064]108        return *this;
109    }
[419]110
[1064]111    /*!
112      Returns the stored pointer (which remains owned by this
113      instance). For empty instances, this method returns NULL.
114    */
115    T *get() {
116        return payload;
117    }
[419]118
[1064]119    /*!
120      Dereferences the stored pointer (which remains owned by
121      this instance). This method may only be called when the
122      stored pointer isn't NULL.
123    */
124    T *operator->() {
125        bdm_assert_debug ( payload, "dereferencing NULL shared pointer" );
126        return payload;
127    }
[419]128
[1064]129    //! Returns a reference to the object pointed to by the stored
130    //! pointer. This method may only be called when the stored pointer
131    //! isn't NULL.
132    T &operator*() {
133        bdm_assert_debug ( payload, "dereferencing NULL shared pointer" );
134        return *payload;
135    }
[419]136
[1064]137    /*!
138      Returns the stored pointer (which remains owned by this
139      instance). For empty instances, this method returns NULL.
140    */
141    const T* get() const {
142        return payload;
143    }
[419]144
[1064]145    //! Returns the stored pointer (which remains owned by this
146    //! instance). This method may only be called when the stored
147    //! pointer isn't NULL.
148    const T *operator->() const {
149        bdm_assert_debug ( payload, "dereferencing NULL shared pointer" );
150        return payload;
151    }
[419]152
[1064]153    //! Returns a reference to the object pointed to by the stored
154    //! pointer. This method may only be called when the stored pointer
155    //! isn't NULL.
156    const T &operator*() const {
157        bdm_assert_debug ( payload, "dereferencing NULL shared pointer" );
158        return *payload;
159    }
[419]160
[1064]161    //! Returns use_count() == 1
162    bool unique() const {
163        return refCnt && ( *refCnt == 1 );
164    }
[419]165
[1064]166    /*!
167      Returns the number of shared_ptr instances (including
168      this instance) that share ownership with this instance. For
169      empty instances, this method returns 0.
170    */
171    long use_count() const {
172        return refCnt ? *refCnt : 0;
173    }
[419]174
[1064]175    /*!
176      \brief Boolean cast
[555]177
[1064]178      This operator returns true if and only if the instance isn't empty.
179    */
180    operator bool() const {
181        return !!payload;
182    }
[419]183
[1064]184    /*!
185      \brief const cast
[570]186
[1064]187      Shared pointer to T can be converted to shared pointer to
188      const T, just like T * can be converted to T const *.
189    */
190    template<typename U>
191    operator shared_ptr<const U>() const {
192        shared_ptr<const U> cptr;
193        cptr.refCnt = refCnt;
194        cptr.payload = payload;
195        add_ref();
196        return cptr;
197    }
[570]198
[1064]199    /*!
200      \brief Efficient swap for shared_ptr.
201     */
202    void swap ( shared_ptr &other ) {
203        std::swap ( payload, other.payload );
204        std::swap ( refCnt, other.refCnt );
205    }
[477]206
[419]207private:
[1064]208    void add_ref() const {
209        if ( refCnt ) {
210            if ( *refCnt == UINT_MAX ) {
211                throw std::overflow_error (
212                    std::string ( "Shared pointer has too many references." ) );
213            }
[419]214
[1064]215            ++*refCnt;
216        }
217    }
[419]218
[1064]219    void del_ref() {
220        if ( refCnt ) {
221            if ( ! ( --*refCnt ) ) {
222                delete payload;
223                delete refCnt;
224            }
225        }
226    }
[419]227};
228
[737]229//! Compare shared pointers
[419]230template<typename T, typename U>
[477]231bool operator== ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
[1064]232    return a.get() == b.get();
[419]233}
234
[737]235//! Compare shared pointers
[419]236template<typename T, typename U>
[477]237bool operator!= ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
[1064]238    return a.get() != b.get();
[419]239}
240
[737]241//! Compare shared pointers
[419]242template<typename T, typename U>
[477]243bool operator< ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
[1064]244    return a.get() < b.get();
[419]245}
246
[529]247/*! \brief A wrapper of shared_ptr which is never empty.
248
249  T must have a default constructor.
250
251  Note that shared_ptr's destructor isn't virtual - don't call delete
252  on pointers to instances of this class.
253 */
254template <typename T>
[737]255class object_ptr : public shared_ptr<T> {
[529]256public:
[1064]257    /*!
258      \brief Default constructor
[529]259
[1064]260      Calls T's default constructor.
261    */
262    object_ptr() : shared_ptr<T> ( new T() ) { }
[529]263
[1064]264    /*!
265      \brief Upcast from shared_ptr<T> to object_ptr<T>
[529]266
[1064]267      \param b The shared pointer, which must not be empty.
268    */
269    object_ptr ( const shared_ptr<T> &b ) : shared_ptr<T> ( b ) {
270        bdm_assert_debug ( this->get(), "object_ptr cannot be empty" );
271    }
[529]272
[1064]273    /*!
274      Constructs an object_ptr that owns the pointer p. p must
275      have been alllocated by new!
276    */
277    object_ptr ( T *p ) : shared_ptr<T> ( p ) {
278        bdm_assert_debug ( p, "object_ptr cannot be empty" );
279    }
[529]280
[1064]281    /*!
282      \brief Assignment operator
283    */
284    object_ptr<T> &operator= ( const object_ptr<T> &other ) {
285        shared_ptr<T>::operator= ( other );
286        return *this;
287    }
[529]288};
289
290#define SHAREDPTR(class_name) typedef bdm::object_ptr< class_name > class_name##_ptr
291
292#define SHAREDPTR2(template_class_name, template_parameter_name) typedef bdm::object_ptr< template_class_name < template_parameter_name > > template_class_name##_##template_parameter_name##_ptr
293
[419]294}
295
296#endif
Note: See TracBrowser for help on using the browser.