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 
00033 template <typename T>
00034 class shared_ptr {
00035         template<class U> friend class shared_ptr;
00036 
00037 private:
00038         T *payload;
00039         unsigned *refCnt;
00040 
00041 public:
00043         shared_ptr() :
00044                         payload ( 0 ),
00045                         refCnt ( 0 ) {
00046         }
00047 
00054         shared_ptr ( T *p ) :
00055                         payload ( p ),
00056                         refCnt ( p ? new unsigned ( 1 ) : 0 ) {
00057         }
00058 
00061         shared_ptr ( const shared_ptr<T> &other ) :
00062                         payload ( other.payload ),
00063                         refCnt ( other.refCnt ) {
00064                 add_ref();
00065         }
00066 
00069         template<typename U>
00070         shared_ptr ( const shared_ptr<U> &other ) :
00071                         payload ( other.payload ),
00072                         refCnt ( other.refCnt ) {
00073                 add_ref();
00074         }
00075 
00076         ~shared_ptr() {
00077                 del_ref();
00078         }
00079 
00080         shared_ptr<T> &operator= ( const shared_ptr<T> &other ) {
00081                 other.add_ref();
00082                 del_ref();
00083 
00084                 payload = other.payload;
00085                 refCnt = other.refCnt;
00086 
00087                 return *this;
00088         }
00089 
00092         T *get() {
00093                 return payload;
00094         }
00095 
00099         T *operator->() {
00100                 it_assert_debug ( payload, "dereferencing NULL" );
00101                 return payload;
00102         }
00103 
00107         T &operator*() {
00108                 it_assert_debug ( payload, "dereferencing NULL" );
00109                 return *payload;
00110         }
00111 
00114         const T* get() const {
00115                 return payload;
00116         }
00117 
00121         const T *operator->() const {
00122                 it_assert_debug ( payload, "dereferencing NULL" );
00123                 return payload;
00124         }
00125 
00129         const T &operator*() const {
00130                 it_assert_debug ( payload, "dereferencing NULL" );
00131                 return *payload;
00132         }
00133 
00134         bool unique() const {
00135                 return refCnt && ( *refCnt == 1 );
00136         }
00137 
00138         long use_count() const {
00139                 return refCnt ? *refCnt : 0;
00140         }
00141 
00142         operator bool() const {
00143                 return payload;
00144         }
00145 
00146         void swap ( shared_ptr &other ) {
00147                 std::swap ( payload, other.payload );
00148                 std::swap ( refCnt, other.refCnt );
00149         }
00150 
00151 private:
00152         void add_ref() const {
00153                 if ( refCnt ) {
00154                         if ( *refCnt == UINT_MAX ) {
00155                                 throw std::overflow_error (
00156                                     std::string ( "Shared pointer has too many references." ) );
00157                         }
00158 
00159                         ++*refCnt;
00160                 }
00161         }
00162 
00163         void del_ref() {
00164                 if ( refCnt ) {
00165                         if ( ! ( --*refCnt ) ) {
00166                                 delete payload;
00167                                 delete refCnt;
00168                         }
00169                 }
00170         }
00171 };
00172 
00174 template<typename T, typename U>
00175 bool operator== ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
00176         return a.get() == b.get();
00177 }
00178 
00180 template<typename T, typename U>
00181 bool operator!= ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
00182         return a.get() != b.get();
00183 }
00184 
00186 template<typename T, typename U>
00187 bool operator< ( shared_ptr<T> const &a, shared_ptr<U> const &b ) {
00188         return a.get() < b.get();
00189 }
00190 
00198 template <typename T>
00199 class object_ptr : public shared_ptr<T>
00200 {
00201 public:
00207         object_ptr() : shared_ptr<T> ( new T() ) { }
00208 
00214         object_ptr ( const shared_ptr<T> &b ) : shared_ptr<T> ( b ) {
00215                 it_assert_debug ( this->get(), "object_ptr cannot be empty" );
00216         }
00217 
00222         object_ptr ( T *p ) : shared_ptr<T> ( p ) {
00223                 it_assert_debug ( p, "object_ptr cannot be empty" );
00224         }
00225 
00226         object_ptr<T> &operator= ( const object_ptr<T> &other ) {
00227                 shared_ptr<T>::operator= ( other );
00228                 return *this;
00229         }
00230 };
00231 
00232 #define SHAREDPTR(class_name) typedef bdm::object_ptr< class_name > class_name##_ptr
00233 
00234 #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
00235 
00236 }
00237 
00238 #endif