00001 #ifndef cow_ptr_H_HEADER_GUARD_
00002 #define cow_ptr_H_HEADER_GUARD_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <algorithm>
00042
00043
00044 template < typename T, typename DT> T * cow_ptr_ConstructAndDestruct_default_allocator_(T*, bool, DT* , void*);
00045
00050 template<typename T>
00051 class cow_ptr
00052 {
00053 typedef T * ( *clone_fct_Type ) (const T *, bool, void*, void*);
00054 struct ref_link
00055 {
00056 ref_link():m_back(NULL), m_front(NULL){}
00057 ref_link *m_back;
00058 ref_link *m_front;
00059 private:
00060 ref_link(const ref_link&);
00061 ref_link& operator=(const ref_link&);
00062 };
00063 mutable ref_link m_ref_link;
00064 T* m_type;
00065 clone_fct_Type m_clone_fct;
00066 public:
00067
00068 template<typename T_obj>
00069 cow_ptr(T_obj* type): m_type(type), m_clone_fct(get_alloc_func(type))
00070 {
00071 #ifdef BOOST_ASSERT
00072 BOOST_ASSERT(type != NULL);
00073 BOOST_ASSERT(typeid(*type) == typeid(T_obj));
00074 #endif //BOOST_ASSERT
00075 }
00076
00077 ~cow_ptr() throw(){release();}
00078
00079 cow_ptr(const cow_ptr& Src):m_type(Src.m_type), m_clone_fct(Src.m_clone_fct){insert_link(&Src.m_ref_link);}
00080 #if !defined(_MSC_VER) || (_MSC_VER > 1200)
00081
00082 template<class CompatibleDerivedT>
00083 cow_ptr(const cow_ptr<CompatibleDerivedT>& Src):m_type(NULL), m_clone_fct(NULL)
00084 {
00085 Src.make_clone(m_type, m_clone_fct);
00086 }
00087 template<class CompatibleDerivedT>
00088 cow_ptr& operator=(const cow_ptr<CompatibleDerivedT>& Src)
00089 {
00090 release();
00091 Src.make_clone(m_type, m_clone_fct);
00092 return *this;
00093 }
00094 #endif //_MSC_VER != 1200
00095
00096 cow_ptr& operator=(const cow_ptr& Src){return assign(Src);}
00097 enum implement_default_object{eYes, eNo};
00098
00099 cow_ptr(implement_default_object use_default_obj = eYes):m_type(NULL), m_clone_fct(NULL)
00100 {
00101 if (use_default_obj == eYes)
00102 assign(GetSetDefaultObject());
00103 }
00104
00105
00106 static void SetDefaultObject(const cow_ptr<T>& NewValue){GetSetDefaultObject(&NewValue);}
00107 typedef T* pointer;
00108 typedef T& reference;
00109 bool operator! () const{return c_ptr() == 0;}
00110 template<class T2>
00111 cow_ptr& equal(const T2& Src){
00112 (*get_ptr()) = (Src);
00113 return *this;
00114 }
00115
00116 inline T* operator->() {return get_ptr();}
00117 inline T& operator*() {return *get_ptr();}
00118 inline const T* operator->()const {return m_type;}
00119 inline const T& operator*() const {return *m_type;}
00120 cow_ptr& operator+=(const cow_ptr& Src){
00121 get_ptr()->operator+=(*Src.c_ptr());
00122 return *this;
00123 }
00124 template<class T2>
00125 cow_ptr& operator+=(const T2& Src){
00126 get_ptr()->operator+=(Src);
00127 return *this;
00128 }
00129 cow_ptr& operator+(const cow_ptr& Src){
00130 get_ptr()->operator+(*Src.c_ptr());
00131 return *this;
00132 }
00133 cow_ptr& operator-=(const cow_ptr& Src){
00134 get_ptr()->operator-=(*Src.c_ptr());
00135 return *this;
00136 }
00137 cow_ptr& operator-(const cow_ptr& Src){
00138 get_ptr()->operator-(*Src.c_ptr());
00139 return *this;
00140 }
00141 clone_fct_Type get_function_ptr()const{return m_clone_fct;}
00142 T* get_ptr()
00143 {
00144 if (is_ref_linked())
00145 {
00146 T* tmp = m_clone_fct(m_type, true, NULL, NULL);
00147 release();
00148 m_type = tmp;
00149 }
00150 return m_type;
00151 }
00152 inline const T* c_ptr()const{return m_type;}
00153 inline const T& c_ref()const{return *m_type;}
00154
00155 void swap(cow_ptr<T> & other)throw(){std::swap(m_ref_link, other.m_ref_link);std::swap(m_type, other.m_type);std::swap(m_clone_fct, other.m_clone_fct);}
00156
00157 bool is_ref_linked()const{return (m_ref_link.m_back || m_ref_link.m_front);}
00158
00159 template<class PT, class FPT> void make_clone(PT*& ptr, FPT& func_ptr) const
00160 {
00161 if (m_type)
00162 {
00163 ptr = m_clone_fct(m_type, true, NULL, NULL);
00164 func_ptr = (FPT)m_clone_fct;
00165 }
00166 else
00167 ptr = NULL;
00168 }
00169 private:
00170 template<typename T_obj>
00171 static clone_fct_Type get_alloc_func(T_obj*)
00172 {
00173 T * ( *tmp ) (T *, bool, T_obj*, void*) = cow_ptr_ConstructAndDestruct_default_allocator_<T,T_obj>;
00174 return (clone_fct_Type)tmp;
00175 }
00176 void release() throw()
00177 {
00178 if (!is_ref_linked()){
00179 m_clone_fct(m_type, false, NULL, NULL);
00180 m_type = NULL;
00181 }
00182 else
00183 {
00184 pop_link();
00185 }
00186 }
00187 void pop_link()
00188 {
00189 if (m_ref_link.m_back)
00190 {
00191 m_ref_link.m_back->m_front = m_ref_link.m_front;
00192 }
00193 if (m_ref_link.m_front)
00194 {
00195 m_ref_link.m_front->m_back = m_ref_link.m_back;
00196 }
00197 m_ref_link.m_front = NULL;
00198 m_ref_link.m_back = NULL;
00199 }
00200 void insert_link(ref_link *Target)
00201 {
00202 m_ref_link.m_back = Target;
00203 m_ref_link.m_front = Target->m_front;
00204 if (m_ref_link.m_front)
00205 {
00206 m_ref_link.m_front->m_back = &m_ref_link;
00207 }
00208 if (m_ref_link.m_back)
00209 {
00210 m_ref_link.m_back->m_front = &m_ref_link;
00211 }
00212 }
00213 template<class CompatibleSmartPtr>
00214 cow_ptr& assign(CompatibleSmartPtr& Src)
00215 {
00216 if (!m_type || Src.is_ref_linked() || m_type != Src.c_ptr())
00217 {
00218 release();
00219 m_type = Src.m_type;
00220 m_clone_fct = Src.m_clone_fct;
00221 insert_link(&Src.m_ref_link);
00222 }
00223 return *this;
00224 }
00225 static cow_ptr<T>& GetSetDefaultObject(const cow_ptr<T>* NewValue = NULL)
00226 {
00227 static cow_ptr<T> DefaultObj(eNo);
00228 if (NewValue && NewValue->m_type)
00229 DefaultObj = *NewValue;
00230 return DefaultObj;
00231 }
00232 };
00233
00234
00235 template<class T, class U> bool operator<(cow_ptr<T> const & a, cow_ptr<U> const & b){return (*a.c_ptr()) < (*b.c_ptr());}
00236 template<class T, class U> bool operator>(cow_ptr<T> const & a, cow_ptr<U> const & b){return (*a.c_ptr()) > (*b.c_ptr());}
00237 template<class T, class U> bool operator<=(cow_ptr<T> const & a, cow_ptr<U> const & b){return (*a.c_ptr()) <= (*b.c_ptr());}
00238 template<class T, class U> bool operator>=(cow_ptr<T> const & a, cow_ptr<U> const & b){return (*a.c_ptr()) >= (*b.c_ptr());}
00239 template<class T, class U> bool operator==(cow_ptr<T> const & a, cow_ptr<U> const & b){return (*a.c_ptr()) == (*b.c_ptr());}
00240 template<class T, class U> bool operator!=(cow_ptr<T> const & a, cow_ptr<U> const & b){return (*a.c_ptr()) != (*b.c_ptr());}
00241
00242 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00243
00244 template<class T> bool operator!=(cow_ptr<T> const & a, cow_ptr<T> const & b){return (*a.c_ptr()) != (*b.c_ptr());}
00245 #endif
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 template < typename T, typename DT> T * cow_ptr_ConstructAndDestruct_default_allocator_(T * ptr, bool bConstruct, DT* , void*) {
00258 if (bConstruct){return new DT(*static_cast<const DT*>(ptr));}
00259 delete const_cast<T*>(ptr);
00260 return NULL;
00261 }
00262
00263
00264 #endif
00265