00001 #ifndef NMWR_GB_COPY_ON_WRITE_PTR_H 00002 #define NMWR_GB_COPY_ON_WRITE_PTR_H 00003 00004 // $LICENSE 00005 00006 00007 00008 00017 #include "Utility/copy-traits.h" 00018 00019 00025 class counted_obj { 00026 public: 00027 void operator++() { ++count;} 00028 void operator--() { 00029 if (--count == 0) 00030 delete this; // calls d'tor of derived class (virtual d'tor!) 00031 } 00032 bool is_shared() const { return (count > 1);} 00033 00034 protected: 00035 counted_obj() : count(0) {} 00036 virtual ~counted_obj() {} // virtual is essential, see op-- above! 00037 00038 private: 00039 unsigned count; 00040 00041 // Forbidden 00042 counted_obj(counted_obj const&); 00043 counted_obj& operator=(counted_obj const&); 00044 }; 00045 00046 00047 00054 template<class T> 00055 class copy_on_write_ptr { 00056 public: 00057 copy_on_write_ptr(T* pt = 0); 00058 copy_on_write_ptr(const copy_on_write_ptr<T>& rhs) 00059 : counter(rhs.counter) {init();} 00060 copy_on_write_ptr<T>& operator=(const copy_on_write_ptr<T>& rhs); 00061 ~copy_on_write_ptr() { --(*counter); } 00062 00063 const T* operator->() const { return (counter->T_ptr);} 00064 const T& operator*() const { return *(counter->T_ptr);} 00065 00066 T& operator*() { copy(); return *(counter->T_ptr);} 00067 T* operator->() { copy(); return (counter->T_ptr);} 00068 00069 private: 00070 struct holder: public counted_obj { 00071 ~holder() { copy_traits<T>::destroy(T_ptr); } 00072 T *T_ptr; 00073 }; 00074 00075 holder *counter; 00076 void init() { ++(*counter);} 00077 void copy(); 00078 }; 00079 00080 00081 template<class T> 00082 inline copy_on_write_ptr<T>::copy_on_write_ptr(T* pt) 00083 : counter(new holder) 00084 { 00085 counter->T_ptr = pt; 00086 init(); 00087 } 00088 00089 template<class T> 00090 inline copy_on_write_ptr<T>& 00091 copy_on_write_ptr<T>::operator=(const copy_on_write_ptr<T>& rhs) 00092 { 00093 if (counter != rhs.counter) { 00094 --(*counter); 00095 counter = rhs.counter; 00096 init(); 00097 } 00098 return *this; 00099 } 00100 00101 template<class T> 00102 inline void copy_on_write_ptr<T>::copy() 00103 { 00104 if(counter->is_shared()) { 00105 T * old_T_ptr = counter->T_ptr; 00106 --(*counter); 00107 counter = new holder; 00108 counter->T_ptr = copy_traits<T>::clone(*old_T_ptr); 00109 ++(*counter); 00110 } 00111 } 00112 00113 00114 #endif