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
Line 
1/*!
2  \file
3  \brief BDM's own smart pointers.
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>
20#include "bdmerror.h"
21
22namespace bdm {
23
24/*! \brief A naive implementation of roughly a subset of the std::tr1::shared_ptr spec
25
26  Really just roughly - it ignores memory
27  exceptions, for example; also note I didn't read the spec.
28
29  The standard template would naturally be preferable, \b if it was
30  included in the standard libraries of all supported compilers - but
31  as of 2009, that's still a problem...
32*/
33template <typename T>
34class shared_ptr {
35    template<class U> friend class shared_ptr;
36
37private:
38    T *payload;
39    unsigned *refCnt;
40
41public:
42    /*!
43      \brief Default constructor
44
45      Creates an empty shared_ptr - one that doesn't point anywhere.
46    */
47    shared_ptr() :
48        payload ( 0 ),
49        refCnt ( 0 ) {
50    }
51
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    }
62
63    /*!
64      \brief Copy constructor
65
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    }
74
75    /*!
76      \brief Generalized copy
77
78      Allows initialization of shared pointer of a base type from
79      raw pointer to a derived type.
80
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    }
90
91    /*!
92      Destructor.
93    */
94    ~shared_ptr() {
95        del_ref();
96    }
97
98    /*!
99      \brief Assignment operator
100    */
101    shared_ptr<T> &operator= ( const shared_ptr<T> &other ) {
102        other.add_ref();
103        del_ref();
104
105        payload = other.payload;
106        refCnt = other.refCnt;
107
108        return *this;
109    }
110
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    }
118
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    }
128
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    }
136
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    }
144
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    }
152
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    }
160
161    //! Returns use_count() == 1
162    bool unique() const {
163        return refCnt && ( *refCnt == 1 );
164    }
165
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    }
174
175    /*!
176      \brief Boolean cast
177
178      This operator returns true if and only if the instance isn't empty.
179    */
180    operator bool() const {
181        return !!payload;
182    }
183
184    /*!
185      \brief const cast
186
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    }
198
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    }
206
207private:
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            }
214
215            ++*refCnt;
216        }
217    }
218
219    void del_ref() {
220        if ( refCnt ) {
221            if ( ! ( --*refCnt ) ) {
222                delete payload;
223                delete refCnt;
224            }
225        }
226    }
227};
228
229//! Compare shared pointers
230template<typename T, typename U>
231bool operator== ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
232    return a.get() == b.get();
233}
234
235//! Compare shared pointers
236template<typename T, typename U>
237bool operator!= ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
238    return a.get() != b.get();
239}
240
241//! Compare shared pointers
242template<typename T, typename U>
243bool operator< ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
244    return a.get() < b.get();
245}
246
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>
255class object_ptr : public shared_ptr<T> {
256public:
257    /*!
258      \brief Default constructor
259
260      Calls T's default constructor.
261    */
262    object_ptr() : shared_ptr<T> ( new T() ) { }
263
264    /*!
265      \brief Upcast from shared_ptr<T> to object_ptr<T>
266
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    }
272
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    }
280
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    }
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
294}
295
296#endif
Note: See TracBrowser for help on using the browser.