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