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

tracked_ptr.hh

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

Generated on Tue Oct 4 2011 15:24:43 for Milena (Olena) by  doxygen 1.7.1