00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00028 #ifndef _COUNTED_PTR_H_
00029 #define _COUNTED_PTR_H_
00030
00031 #define DEBUG_COUNTED_PTR 0
00032
00039 template <typename _Tp> class counted_ptr
00040 {
00041 private:
00044 class counter
00045 {
00046 public:
00048 _Tp* p;
00050 unsigned int c;
00051
00052 public:
00054 counter(_Tp* ptr = 0, unsigned int cntr = 1) : p(ptr), c(cntr) {}
00055 };
00056
00057 private:
00059 counter *_cntr;
00060
00061 public:
00063 typedef _Tp element_type;
00064
00065 public:
00068 explicit counted_ptr(_Tp* p = 0) : _cntr(0)
00069 { if(p) _cntr = new counter(p); }
00072 ~counted_ptr()
00073 { delete_reference(); }
00075 counted_ptr(const counted_ptr& r) throw()
00076 { new_reference(r._cntr); }
00077
00081 counted_ptr& operator=(const counted_ptr& r)
00082 {
00083 if(this != &r)
00084 {
00085 delete_reference();
00086 new_reference(r._cntr);
00087 }
00088 return *this;
00089 }
00090
00092 counted_ptr& operator=(element_type* r)
00093 {
00094 delete_reference();
00095 if(_cntr) delete _cntr;
00096 if(r)
00097 _cntr = new counter(r);
00098 else
00099 _cntr = 0;
00100 return *this;
00101 }
00102
00104 template <typename _Tq>
00105 counted_ptr(const counted_ptr<_Tq>& r) throw()
00106 { new_reference(r._cntr); }
00107
00111 template <typename _Tq>
00112 counted_ptr& operator=(const counted_ptr<_Tq>& r)
00113 {
00114 if(this != &r)
00115 {
00116 delete_reference();
00117 new_reference(r._cntr);
00118 }
00119 return *this;
00120 }
00121
00122 #if DEBUG_COUNTED_PTR
00123
00124 unsigned int get_count() const throw()
00125 { return _cntr ? _cntr->c : 0; }
00126 #endif
00127
00129 _Tp& operator*() const throw()
00130 { return *_cntr->p; }
00132 _Tp* operator->() const throw()
00133 { return _cntr->p; }
00135 _Tp* get() const throw()
00136 { return _cntr ? _cntr->p : 0; }
00138 bool is_unique() const throw()
00139 { return (_cntr ? _cntr->c == 1 : true); }
00140
00141 private:
00144 void new_reference(counter* cntr) throw()
00145 {
00146 _cntr = cntr;
00147 if (cntr) ++cntr->c;
00148 }
00149
00153 void delete_reference()
00154 {
00155 #if DEBUG_COUNTED_PTR
00156 std::cerr << "delete_reference(): " << _cntr ? _cntr->c : 0;
00157 #endif
00158 if(_cntr)
00159 {
00160 if(--_cntr->c == 0)
00161 {
00162 #if DEBUG_COUNTED_PTR
00163 std::cerr << "count == 0: deleting";
00164 #endif
00165 delete _cntr->p;
00166 delete _cntr;
00167 }
00168 _cntr = 0;
00169 }
00170 #if DEBUG_COUNTED_PTR
00171 std::cerr << std::endl;
00172 #endif
00173 }
00174 };
00175
00176 #endif // _COUNTED_PTR_H_