root/library/bdm/shared_ptr.h @ 737

Revision 737, 6.6 kB (checked in by mido, 15 years ago)

ASTYLER RUN OVER THE WHOLE LIBRARY, JUPEE

  • 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 {
[477]35        template<class U> friend class shared_ptr;
[461]36
[419]37private:
[477]38        T *payload;
39        unsigned *refCnt;
[419]40
41public:
[555]42        /*!
43          \brief Default constructor
44
45          Creates an empty shared_ptr - one that doesn't point anywhere.
46        */
[477]47        shared_ptr() :
48                        payload ( 0 ),
49                        refCnt ( 0 ) {
50        }
[419]51
[737]52        /*!
[529]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        */
[477]58        shared_ptr ( T *p ) :
59                        payload ( p ),
60                        refCnt ( p ? new unsigned ( 1 ) : 0 ) {
61        }
[419]62
[555]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        */
[477]69        shared_ptr ( const shared_ptr<T> &other ) :
70                        payload ( other.payload ),
71                        refCnt ( other.refCnt ) {
72                add_ref();
73        }
[419]74
[555]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        */
[477]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
[555]91        /*!
92          Destructor.
93        */
[477]94        ~shared_ptr() {
95                del_ref();
96        }
[419]97
[555]98        /*!
99          \brief Assignment operator
100        */
[529]101        shared_ptr<T> &operator= ( const shared_ptr<T> &other ) {
[477]102                other.add_ref();
103                del_ref();
[419]104
[477]105                payload = other.payload;
106                refCnt = other.refCnt;
[419]107
[477]108                return *this;
109        }
[419]110
[555]111        /*!
112          Returns the stored pointer (which remains owned by this
113          instance). For empty instances, this method returns NULL.
114        */
[477]115        T *get() {
116                return payload;
117        }
[419]118
[555]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        */
[477]124        T *operator->() {
[737]125                if ( !payload ) {
126                        abort();
127                };// "dereferencing NULL" );
[477]128                return payload;
129        }
[419]130
[477]131        //! Returns a reference to the object pointed to by the stored
132        //! pointer. This method may only be called when the stored pointer
133        //! isn't NULL.
134        T &operator*() {
[565]135                bdm_assert_debug ( payload, "dereferencing NULL" );
[477]136                return *payload;
137        }
[419]138
[555]139        /*!
140          Returns the stored pointer (which remains owned by this
141          instance). For empty instances, this method returns NULL.
142        */
[477]143        const T* get() const {
144                return payload;
145        }
[419]146
[477]147        //! Returns the stored pointer (which remains owned by this
148        //! instance). This method may only be called when the stored
149        //! pointer isn't NULL.
150        const T *operator->() const {
[565]151                bdm_assert_debug ( payload, "dereferencing NULL" );
[477]152                return payload;
153        }
[419]154
[477]155        //! Returns a reference to the object pointed to by the stored
156        //! pointer. This method may only be called when the stored pointer
157        //! isn't NULL.
158        const T &operator*() const {
[565]159                bdm_assert_debug ( payload, "dereferencing NULL" );
[477]160                return *payload;
161        }
[419]162
[555]163        //! Returns use_count() == 1
[477]164        bool unique() const {
165                return refCnt && ( *refCnt == 1 );
166        }
[419]167
[555]168        /*!
169          Returns the number of shared_ptr instances (including
170          this instance) that share ownership with this instance. For
171          empty instances, this method returns 0.
172        */
[477]173        long use_count() const {
174                return refCnt ? *refCnt : 0;
175        }
[419]176
[555]177        /*!
178          \brief Boolean cast
179
180          This operator returns true if and only if the instance isn't empty.
181        */
[477]182        operator bool() const {
[554]183                return !!payload;
[477]184        }
[419]185
[555]186        /*!
[570]187          \brief const cast
188
189          Shared pointer to T can be converted to shared pointer to
190          const T, just like T * can be converted to T const *.
191        */
192        template<typename U>
193        operator shared_ptr<const U>() const {
[737]194                shared_ptr<const U> cptr;
[570]195                cptr.refCnt = refCnt;
196                cptr.payload = payload;
197                add_ref();
198                return cptr;
199        }
200
201        /*!
[555]202          \brief Efficient swap for shared_ptr.
203         */
[477]204        void swap ( shared_ptr &other ) {
205                std::swap ( payload, other.payload );
206                std::swap ( refCnt, other.refCnt );
207        }
208
[419]209private:
[477]210        void add_ref() const {
211                if ( refCnt ) {
212                        if ( *refCnt == UINT_MAX ) {
213                                throw std::overflow_error (
214                                    std::string ( "Shared pointer has too many references." ) );
215                        }
[419]216
[477]217                        ++*refCnt;
218                }
[419]219        }
220
[477]221        void del_ref() {
222                if ( refCnt ) {
223                        if ( ! ( --*refCnt ) ) {
224                                delete payload;
225                                delete refCnt;
226                        }
227                }
[419]228        }
229};
230
[737]231//! Compare shared pointers
[419]232template<typename T, typename U>
[477]233bool operator== ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
234        return a.get() == b.get();
[419]235}
236
[737]237//! Compare shared pointers
[419]238template<typename T, typename U>
[477]239bool operator!= ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
240        return a.get() != b.get();
[419]241}
242
[737]243//! Compare shared pointers
[419]244template<typename T, typename U>
[477]245bool operator< ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
246        return a.get() < b.get();
[419]247}
248
[529]249/*! \brief A wrapper of shared_ptr which is never empty.
250
251  T must have a default constructor.
252
253  Note that shared_ptr's destructor isn't virtual - don't call delete
254  on pointers to instances of this class.
255 */
256template <typename T>
[737]257class object_ptr : public shared_ptr<T> {
[529]258public:
259        /*!
260          \brief Default constructor
261
262          Calls T's default constructor.
263        */
264        object_ptr() : shared_ptr<T> ( new T() ) { }
265
266        /*!
267          \brief Upcast from shared_ptr<T> to object_ptr<T>
268
269          \param b The shared pointer, which must not be empty.
270        */
271        object_ptr ( const shared_ptr<T> &b ) : shared_ptr<T> ( b ) {
[565]272                bdm_assert_debug ( this->get(), "object_ptr cannot be empty" );
[529]273        }
274
[737]275        /*!
[529]276          Constructs an object_ptr that owns the pointer p. p must
277          have been alllocated by new!
278        */
279        object_ptr ( T *p ) : shared_ptr<T> ( p ) {
[565]280                bdm_assert_debug ( p, "object_ptr cannot be empty" );
[529]281        }
282
[555]283        /*!
284          \brief Assignment operator
285        */
[529]286        object_ptr<T> &operator= ( const object_ptr<T> &other ) {
287                shared_ptr<T>::operator= ( other );
288                return *this;
289        }
290};
291
292#define SHAREDPTR(class_name) typedef bdm::object_ptr< class_name > class_name##_ptr
293
294#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
295
[419]296}
297
298#endif
Note: See TracBrowser for help on using the browser.