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
00026 #ifndef MLN_UTIL_TRACKED_PTR_HH
00027 # define MLN_UTIL_TRACKED_PTR_HH
00028
00032
00033 # include <set>
00034 # include <iostream>
00035
00036 # include <mln/core/contract.hh>
00037
00038
00039
00040 namespace mln
00041 {
00042
00043 namespace util
00044 {
00045
00049
00050 template <typename T>
00051 struct tracked_ptr
00052 {
00053 typedef tracked_ptr<T> self_t;
00054 typedef std::set<self_t*> holders_t;
00055
00056 T* ptr_;
00057 holders_t* holders_;
00058
00060 operator bool() const;
00061
00063 bool operator !() const;
00064
00068 const T* operator->() const;
00069
00073 T* operator->();
00074
00077 tracked_ptr();
00078 tracked_ptr(T* ptr);
00080 tracked_ptr(const tracked_ptr<T>& rhs);
00082
00084 tracked_ptr<T>& operator=(const tracked_ptr<T>& rhs);
00085
00087 tracked_ptr<T>& operator=(T* ptr);
00088
00090 ~tracked_ptr();
00091
00092 bool run_() const;
00093
00094 void clean_();
00095
00096 };
00097
00098
00099
00100
00101 # ifndef MLN_INCLUDE_ONLY
00102
00103 template <typename T>
00104 inline
00105 tracked_ptr<T>::operator bool() const
00106 {
00107 mln_invariant(run_());
00108 return ptr_ != 0;
00109 }
00110
00111 template <typename T>
00112 inline
00113 bool tracked_ptr<T>::operator !() const
00114 {
00115 mln_invariant(run_());
00116 return ! bool(*this);
00117 }
00118
00119 template <typename T>
00120 inline
00121 const T* tracked_ptr<T>::operator->() const
00122 {
00123 mln_invariant(run_());
00124 mln_precondition(ptr_ != 0);
00125 return ptr_;
00126 }
00127
00128 template <typename T>
00129 inline
00130 T* tracked_ptr<T>::operator->()
00131 {
00132 mln_invariant(run_());
00133 mln_precondition(ptr_ != 0);
00134 return ptr_;
00135 }
00136
00137 template <typename T>
00138 inline
00139 tracked_ptr<T>::tracked_ptr() :
00140 ptr_(0),
00141 holders_(0)
00142 {
00143 mln_invariant(run_());
00144 }
00145
00146 template <typename T>
00147 inline
00148 tracked_ptr<T>::tracked_ptr(T* ptr) :
00149 ptr_(ptr)
00150 {
00151 typedef std::set<tracked_ptr<T>*> holders_t;
00152
00153 if (ptr == 0)
00154 holders_ = 0;
00155 else
00156 {
00157 holders_ = new holders_t;
00158 holders_->insert(this);
00159 }
00160 mln_invariant(run_());
00161 }
00162
00163 template <typename T>
00164 inline
00165 tracked_ptr<T>::tracked_ptr(const tracked_ptr<T>& rhs) :
00166 ptr_(rhs.ptr_),
00167 holders_(rhs.holders_)
00168 {
00169 mln_invariant(rhs.run_());
00170 if (ptr_ != 0)
00171 holders_->insert(this);
00172 mln_invariant(run_());
00173 }
00174
00175 template <typename T>
00176 inline
00177 tracked_ptr<T>& tracked_ptr<T>::operator=(const tracked_ptr<T>& rhs)
00178 {
00179 mln_invariant(run_());
00180 mln_invariant(rhs.run_());
00181 if (&rhs == this || rhs.ptr_ == ptr_)
00182
00183 return *this;
00184 clean_();
00185 ptr_ = rhs.ptr_;
00186 holders_ = rhs.holders_;
00187
00188 if (holders_ != 0)
00189 holders_->insert(this);
00190 return *this;
00191 }
00192
00193 template <typename T>
00194 inline
00195 tracked_ptr<T>& tracked_ptr<T>::operator=(T* ptr)
00196 {
00197 typedef std::set<tracked_ptr<T>*> holders_t;
00198
00199 mln_invariant(run_());
00200 if (ptr == ptr_)
00201
00202 return *this;
00203 clean_();
00204 ptr_ = ptr;
00205 if (ptr == 0)
00206 holders_ = 0;
00207 else
00208 {
00209 holders_ = new holders_t;
00210 holders_->insert(this);
00211 }
00212 return *this;
00213 }
00214
00215 template <typename T>
00216 inline
00217 tracked_ptr<T>::~tracked_ptr()
00218 {
00219 clean_();
00220 }
00221
00222 template <typename T>
00223 inline
00224 bool tracked_ptr<T>::run_() const
00225 {
00226 typedef std::set<tracked_ptr<T>*> holders_t;
00227
00228 mln_invariant((ptr_ && holders_) || (! ptr_ && ! holders_));
00229 if (ptr_ == 0)
00230 return true;
00231 mln_invariant(holders_->size() > 0);
00232 tracked_ptr<T>* this_ = const_cast<tracked_ptr<T>*>(this);
00233 mln_invariant(holders_->find(this_) != holders_->end());
00234 this_ = 0;
00235 typename holders_t::const_iterator i;
00236 for (i = holders_->begin(); i != holders_->end(); ++i)
00237 mln_invariant((*i)->ptr_ == ptr_);
00238 return true;
00239 }
00240
00241 template <typename T>
00242 inline
00243 void tracked_ptr<T>::clean_()
00244 {
00245 mln_invariant(run_());
00246 if (ptr_ == 0)
00247
00248 return;
00249 if (holders_->size() == 1)
00250 {
00251 delete ptr_;
00252 delete holders_;
00253 }
00254 else
00255 holders_->erase(this);
00256 ptr_ = 0;
00257 holders_ = 0;
00258 mln_invariant(run_());
00259 }
00260
00261 template <typename T>
00262 inline
00263 std::ostream& operator<<(std::ostream& ostr, const tracked_ptr<T>& tp)
00264 {
00265 typedef std::set<tracked_ptr<T>*> holders_t;
00266
00267 ostr << "tracked_ptr @ " << (&tp)
00268 << " { ptr = " << tp.ptr_
00269 << " / holders = ";
00270 if (tp.holders_ == 0)
00271 ostr << "0";
00272 else
00273 {
00274 typename holders_t::const_iterator i;
00275 for (i = tp.holders_->begin(); i != tp.holders_->end(); ++i)
00276 ostr << (*i) << ' ';
00277 }
00278 ostr << " }";
00279 return ostr;
00280 }
00281
00282
00283 # endif // ! MLN_INCLUDE_ONLY
00284
00285 }
00286
00287 }
00288
00289
00290 #endif // ! MLN_UTIL_TRACKED_PTR_HH