root/library/bdm/shared_ptr.h @ 420

Revision 420, 4.0 kB (checked in by vbarta, 15 years ago)

some inline documentation, using it_assert_debug (like other library classes)

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 {
30private:
31    T *payload;
32    unsigned *refCnt;
33
34public:
35    //! Creates an empty shared_ptr - one that doesn't point anywhere.
36    shared_ptr():
37        payload(0),
38        refCnt(0)
39    {
40    }
41
42    //! Constructs a shared_ptr that owns the pointer p (unless p is
43    //! null, in which case this constructor creates an empty
44    //! shared_ptr).
45    shared_ptr(T *p):
46        payload(p),
47        refCnt(p ? new unsigned(1) : 0)
48    {
49    }
50
51    //! If other is empty, constructs an empty shared_ptr; otherwise,
52    //! constructs a shared_ptr that shares ownership with other.
53    shared_ptr(const shared_ptr &other):
54        payload(other.payload),
55        refCnt(other.refCnt)
56    {
57        add_ref();
58    }
59
60    ~shared_ptr()
61    {
62        del_ref();
63    }
64
65    shared_ptr &operator=(const shared_ptr &other)
66    {
67        other.add_ref();
68        del_ref();
69
70        payload = other.payload;
71        refCnt = other.refCnt;
72
73        return *this;
74    }
75
76    //! Returns the stored pointer (which remains owned by this
77    //! instance).
78    T *get() { return payload; }
79
80    //! Returns the stored pointer (which remains owned by this
81    //! instance). This method may only be called when the stored
82    //! pointer isn't NULL.
83    T *operator->()
84    {
85        it_assert_debug(payload, "dereferencing NULL");
86        return payload;
87    }
88
89    //! Returns a reference to the object pointed to by the stored
90    //! pointer. This method may only be called when the stored pointer
91    //! isn't NULL.
92    T &operator*()
93    {
94        it_assert_debug(payload, "dereferencing NULL");
95        return *payload;
96    }
97
98    //! Returns the stored pointer (which remains owned by this
99    //! instance).
100    const T* get() const { return payload; }
101
102    //! Returns the stored pointer (which remains owned by this
103    //! instance). This method may only be called when the stored
104    //! pointer isn't NULL.
105    const T *operator->() const
106    {
107        it_assert_debug(payload, "dereferencing NULL");
108        return payload;
109    }
110
111    //! Returns a reference to the object pointed to by the stored
112    //! pointer. This method may only be called when the stored pointer
113    //! isn't NULL.
114    const T &operator*() const
115    {
116        it_assert_debug(payload, "dereferencing NULL");
117        return *payload;
118    }
119
120    bool unique() const
121    {
122        return refCnt && (*refCnt == 1);
123    }
124
125    long use_count() const
126    {
127        return refCnt ? *refCnt : 0;
128    }
129
130    operator bool() const
131    {
132      return payload;
133    }
134
135    void swap(shared_ptr &other)
136    {
137        std::swap(payload, other.payload);
138        std::swap(refCnt, other.refCnt);
139    }
140
141private:
142    void add_ref() const
143    {
144        if (refCnt) {
145            if (*refCnt == UINT_MAX) {
146                throw std::overflow_error(
147                    std::string("Shared pointer has too many references."));
148            }
149
150            ++*refCnt;
151        }
152    }
153
154    void del_ref()
155    {
156        if (refCnt) {
157            if (!(--*refCnt)) {
158                delete payload;
159                delete refCnt;
160            }
161        }
162    }
163};
164
165template<typename T, typename U>
166bool operator==(shared_ptr<T> const &a, shared_ptr<U> const &b)
167{
168    return a.get() == b.get();
169}
170
171template<typename T, typename U>
172bool operator!=(shared_ptr<T> const &a, shared_ptr<U> const &b)
173{
174    return a.get() != b.get();
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
183}
184
185#endif
Note: See TracBrowser for help on using the browser.