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