00001
00013 #ifndef shared_ptr_h
00014 #define shared_ptr_h
00015
00016 #include <limits.h>
00017 #include <algorithm>
00018 #include <stdexcept>
00019 #include <string>
00020 #include "itpp_ext.h"
00021
00022 namespace bdm {
00023
00025
00026
00027
00028 template <typename T>
00029 class shared_ptr {
00030 template<class U> friend class shared_ptr;
00031
00032 private:
00033 T *payload;
00034 unsigned *refCnt;
00035
00036 public:
00038 shared_ptr():
00039 payload(0),
00040 refCnt(0)
00041 {
00042 }
00043
00047 shared_ptr(T *p):
00048 payload(p),
00049 refCnt(p ? new unsigned(1) : 0)
00050 {
00051 }
00052
00055 shared_ptr(const shared_ptr<T> &other):
00056 payload(other.payload),
00057 refCnt(other.refCnt)
00058 {
00059 add_ref();
00060 }
00061
00064 template<typename U>
00065 shared_ptr(const shared_ptr<U> &other):
00066 payload(other.payload),
00067 refCnt(other.refCnt)
00068 {
00069 add_ref();
00070 }
00071
00072 ~shared_ptr()
00073 {
00074 del_ref();
00075 }
00076
00077 shared_ptr &operator=(const shared_ptr &other)
00078 {
00079 other.add_ref();
00080 del_ref();
00081
00082 payload = other.payload;
00083 refCnt = other.refCnt;
00084
00085 return *this;
00086 }
00087
00090 T *get() { return payload; }
00091
00095 T *operator->()
00096 {
00097 it_assert_debug(payload, "dereferencing NULL");
00098 return payload;
00099 }
00100
00104 T &operator*()
00105 {
00106 it_assert_debug(payload, "dereferencing NULL");
00107 return *payload;
00108 }
00109
00112 const T* get() const { return payload; }
00113
00117 const T *operator->() const
00118 {
00119 it_assert_debug(payload, "dereferencing NULL");
00120 return payload;
00121 }
00122
00126 const T &operator*() const
00127 {
00128 it_assert_debug(payload, "dereferencing NULL");
00129 return *payload;
00130 }
00131
00132 bool unique() const
00133 {
00134 return refCnt && (*refCnt == 1);
00135 }
00136
00137 long use_count() const
00138 {
00139 return refCnt ? *refCnt : 0;
00140 }
00141
00142 operator bool() const
00143 {
00144 return payload;
00145 }
00146
00147 void swap(shared_ptr &other)
00148 {
00149 std::swap(payload, other.payload);
00150 std::swap(refCnt, other.refCnt);
00151 }
00152
00153 private:
00154 void add_ref() const
00155 {
00156 if (refCnt) {
00157 if (*refCnt == UINT_MAX) {
00158 throw std::overflow_error(
00159 std::string("Shared pointer has too many references."));
00160 }
00161
00162 ++*refCnt;
00163 }
00164 }
00165
00166 void del_ref()
00167 {
00168 if (refCnt) {
00169 if (!(--*refCnt)) {
00170 delete payload;
00171 delete refCnt;
00172 }
00173 }
00174 }
00175 };
00176
00177 template<typename T, typename U>
00178 bool operator==(shared_ptr<T> const &a, shared_ptr<U> const &b)
00179 {
00180 return a.get() == b.get();
00181 }
00182
00183 template<typename T, typename U>
00184 bool operator!=(shared_ptr<T> const &a, shared_ptr<U> const &b)
00185 {
00186 return a.get() != b.get();
00187 }
00188
00189 template<typename T, typename U>
00190 bool operator<(shared_ptr<T> const &a, shared_ptr<U> const &b)
00191 {
00192 return a.get() < b.get();
00193 }
00194
00195 }
00196
00197 #endif