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