• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

tracked_ptr.hh

00001 // Copyright (C) 2006, 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
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         // no-op
00183         return *this;
00184       clean_();
00185       ptr_ = rhs.ptr_;
00186       holders_ = rhs.holders_;
00187       // If ptr == 0, holders_ == 0 so we cannot insert anything in it.
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         // no-op
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         // no-op
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   } // end of namespace mln::util
00286 
00287 } // end of namespace mln
00288 
00289 
00290 #endif // ! MLN_UTIL_TRACKED_PTR_HH

Generated on Thu Sep 8 2011 18:32:42 for Milena (Olena) by  doxygen 1.7.1