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