root/library/bdm/shared_ptr.h @ 461

Revision 461, 4.4 kB (checked in by vbarta, 15 years ago)

mpdf (& its dependencies) reformat: now using shared_ptr, moved virtual method bodies to .cpp

Line 
1/*!
2  \file
3  \brief BDM's own smart pointer.
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 "itpp_ext.h"
21
22namespace bdm {
23
24//! A naive implementation of roughly a subset of the std::tr1:shared_ptr spec (really just roughly - it ignores memory exceptions, for example; also note I didn't read the spec).
25// The standard template would naturally be preferable, _if_ it was
26// included in the standard libraries of all supported compilers - but
27// that's exactly what remains to be seen...
28template <typename T>
29class shared_ptr {
30    template<class U> friend class shared_ptr;
31
32private:
33    T *payload;
34    unsigned *refCnt;
35
36public:
37    //! Creates an empty shared_ptr - one that doesn't point anywhere.
38    shared_ptr():
39        payload(0),
40        refCnt(0)
41    {
42    }
43
44    //! Constructs a shared_ptr that owns the pointer p (unless p is
45    //! null, in which case this constructor creates an empty
46    //! shared_ptr).
47    shared_ptr(T *p):
48        payload(p),
49        refCnt(p ? new unsigned(1) : 0)
50    {
51    }
52
53    //! If other is empty, constructs an empty shared_ptr; otherwise,
54    //! constructs a shared_ptr that shares ownership with other.
55    shared_ptr(const shared_ptr<T> &other):
56        payload(other.payload),
57        refCnt(other.refCnt)
58    {
59        add_ref();
60    }
61     
62    //! If other is empty, constructs an empty shared_ptr; otherwise,
63    //! constructs a shared_ptr that shares ownership with other.
64    template<typename U>
65    shared_ptr(const shared_ptr<U> &other):
66        payload(other.payload),
67        refCnt(other.refCnt)
68    {
69        add_ref();
70    }
71
72    ~shared_ptr()
73    {
74        del_ref();
75    }
76
77    shared_ptr &operator=(const shared_ptr &other)
78    {
79        other.add_ref();
80        del_ref();
81
82        payload = other.payload;
83        refCnt = other.refCnt;
84
85        return *this;
86    }
87
88    //! Returns the stored pointer (which remains owned by this
89    //! instance).
90    T *get() { return payload; }
91
92    //! Returns the stored pointer (which remains owned by this
93    //! instance). This method may only be called when the stored
94    //! pointer isn't NULL.
95    T *operator->()
96    {
97        it_assert_debug(payload, "dereferencing NULL");
98        return payload;
99    }
100
101    //! Returns a reference to the object pointed to by the stored
102    //! pointer. This method may only be called when the stored pointer
103    //! isn't NULL.
104    T &operator*()
105    {
106        it_assert_debug(payload, "dereferencing NULL");
107        return *payload;
108    }
109
110    //! Returns the stored pointer (which remains owned by this
111    //! instance).
112    const T* get() const { return payload; }
113
114    //! Returns the stored pointer (which remains owned by this
115    //! instance). This method may only be called when the stored
116    //! pointer isn't NULL.
117    const T *operator->() const
118    {
119        it_assert_debug(payload, "dereferencing NULL");
120        return payload;
121    }
122
123    //! Returns a reference to the object pointed to by the stored
124    //! pointer. This method may only be called when the stored pointer
125    //! isn't NULL.
126    const T &operator*() const
127    {
128        it_assert_debug(payload, "dereferencing NULL");
129        return *payload;
130    }
131
132    bool unique() const
133    {
134        return refCnt && (*refCnt == 1);
135    }
136
137    long use_count() const
138    {
139        return refCnt ? *refCnt : 0;
140    }
141
142    operator bool() const
143    {
144      return payload;
145    }
146
147    void swap(shared_ptr &other)
148    {
149        std::swap(payload, other.payload);
150        std::swap(refCnt, other.refCnt);
151    }
152
153private:
154    void add_ref() const
155    {
156        if (refCnt) {
157            if (*refCnt == UINT_MAX) {
158                throw std::overflow_error(
159                    std::string("Shared pointer has too many references."));
160            }
161
162            ++*refCnt;
163        }
164    }
165
166    void del_ref()
167    {
168        if (refCnt) {
169            if (!(--*refCnt)) {
170                delete payload;
171                delete refCnt;
172            }
173        }
174    }
175};
176
177template<typename T, typename U>
178bool operator==(shared_ptr<T> const &a, shared_ptr<U> const &b)
179{
180    return a.get() == b.get();
181}
182
183template<typename T, typename U>
184bool operator!=(shared_ptr<T> const &a, shared_ptr<U> const &b)
185{
186    return a.get() != b.get();
187}
188
189template<typename T, typename U>
190bool operator<(shared_ptr<T> const &a, shared_ptr<U> const &b)
191{
192    return a.get() < b.get();
193}
194
195}
196
197#endif
Note: See TracBrowser for help on using the browser.