$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tracked_ptr.hh
1 // Copyright (C) 2006, 2007, 2008, 2009, 2010 EPITA Research and
2 // Development Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_UTIL_TRACKED_PTR_HH
28 # define MLN_UTIL_TRACKED_PTR_HH
29 
33 
34 # include <set>
35 # include <iostream>
36 
37 # include <mln/core/contract.hh>
38 
39 
40 
41 namespace mln
42 {
43 
44  namespace util
45  {
46 
50  //
51  template <typename T>
52  struct tracked_ptr
53  {
55  typedef std::set<self_t*> holders_t;
56 
57  T* ptr_;
59 
61  operator bool() const;
62 
64  bool operator !() const;
65 
69  const T& operator*() const;
70 
74  T& operator*();
75 
79  const T* operator->() const;
80 
84  T* operator->();
85 
88 
89  tracked_ptr();
90  tracked_ptr(T* ptr);
93 
95 
98 
100  tracked_ptr<T>& operator=(T* ptr);
101 
103  ~tracked_ptr();
104 
105  bool run_() const;
106 
107  void clean_();
108 
109  };
110 
111 
112 
113 
114 # ifndef MLN_INCLUDE_ONLY
115 
116  template <typename T>
117  inline
119  {
120  mln_invariant(run_());
121  return ptr_ != 0;
122  }
123 
124  template <typename T>
125  inline
126  bool tracked_ptr<T>::operator !() const
127  {
128  mln_invariant(run_());
129  return ! bool(*this);
130  }
131 
132  template <typename T>
133  inline
134  const T& tracked_ptr<T>::operator*() const
135  {
136  mln_invariant(run_());
137  mln_precondition(ptr_ != 0);
138  return *ptr_;
139  }
140 
141  template <typename T>
142  inline
144  {
145  mln_invariant(run_());
146  mln_precondition(ptr_ != 0);
147  return *ptr_;
148  }
149 
150  template <typename T>
151  inline
152  const T* tracked_ptr<T>::operator->() const
153  {
154  mln_invariant(run_());
155  mln_precondition(ptr_ != 0);
156  return ptr_;
157  }
158 
159  template <typename T>
160  inline
162  {
163  mln_invariant(run_());
164  mln_precondition(ptr_ != 0);
165  return ptr_;
166  }
167 
168  template <typename T>
169  inline
171  ptr_(0),
172  holders_(0)
173  {
174  mln_invariant(run_());
175  }
176 
177  template <typename T>
178  inline
179  tracked_ptr<T>::tracked_ptr(T* ptr) :
180  ptr_(ptr)
181  {
182  if (ptr == 0)
183  holders_ = 0;
184  else
185  {
186  holders_ = new holders_t;
187  holders_->insert(this);
188  }
189  mln_invariant(run_());
190  }
191 
192  template <typename T>
193  inline
194  tracked_ptr<T>::tracked_ptr(const tracked_ptr<T>& rhs) :
195  ptr_(rhs.ptr_),
196  holders_(rhs.holders_)
197  {
198  mln_invariant(rhs.run_());
199  if (ptr_ != 0)
200  holders_->insert(this);
201  mln_invariant(run_());
202  }
203 
204  template <typename T>
205  inline
206  tracked_ptr<T>& tracked_ptr<T>::operator=(const tracked_ptr<T>& rhs)
207  {
208  mln_invariant(run_());
209  mln_invariant(rhs.run_());
210  if (&rhs == this || rhs.ptr_ == ptr_)
211  // no-op
212  return *this;
213  clean_();
214  ptr_ = rhs.ptr_;
215  holders_ = rhs.holders_;
216  // If ptr == 0, holders_ == 0 so we cannot insert anything in it.
217  if (holders_ != 0)
218  holders_->insert(this);
219  mln_invariant(run_());
220  return *this;
221  }
222 
223  template <typename T>
224  inline
225  tracked_ptr<T>& tracked_ptr<T>::operator=(T* ptr)
226  {
227  mln_invariant(run_());
228  if (ptr == ptr_)
229  // no-op
230  return *this;
231  clean_();
232  ptr_ = ptr;
233  if (ptr == 0)
234  holders_ = 0;
235  else
236  {
237  holders_ = new holders_t;
238  holders_->insert(this);
239  }
240  mln_invariant(run_());
241  return *this;
242  }
243 
244  template <typename T>
245  inline
246  tracked_ptr<T>::~tracked_ptr()
247  {
248  clean_();
249  }
250 
251  template <typename T>
252  inline
253  bool tracked_ptr<T>::run_() const
254  {
255  mln_invariant((ptr_ && holders_) || (! ptr_ && ! holders_));
256  if (ptr_ == 0)
257  return true;
258  mln_invariant(holders_->size() > 0);
259  tracked_ptr<T>* this_ = const_cast<tracked_ptr<T>*>(this);
260  mln_invariant(holders_->find(this_) != holders_->end());
261  this_ = 0;
262  typename holders_t::const_iterator i;
263  for (i = holders_->begin(); i != holders_->end(); ++i)
264  mln_invariant((*i)->ptr_ == ptr_);
265  return true;
266  }
267 
268  template <typename T>
269  inline
270  void tracked_ptr<T>::clean_()
271  {
272  mln_invariant(run_());
273  if (ptr_ == 0)
274  // no-op
275  return;
276  if (holders_->size() == 1)
277  {
278  delete ptr_;
279  delete holders_;
280  }
281  else
282  holders_->erase(this);
283  ptr_ = 0;
284  holders_ = 0;
285  mln_invariant(run_());
286  }
287 
288  template <typename T>
289  inline
290  std::ostream& operator<<(std::ostream& ostr, const tracked_ptr<T>& tp)
291  {
292  typedef std::set<tracked_ptr<T>*> holders_t;
293 
294  mln_invariant(tp.run_());
295  ostr << "tracked_ptr ../../../../doc/ " << (&tp)
296  << " { ptr = " << tp.ptr_
297  << " / holders = ";
298  if (tp.holders_ == 0)
299  ostr << "0";
300  else
301  {
302  typename holders_t::const_iterator i;
303  for (i = tp.holders_->begin(); i != tp.holders_->end(); ++i)
304  ostr << (*i) << ' ';
305  }
306  ostr << " }";
307  return ostr;
308  }
309 
310 
311 # endif // ! MLN_INCLUDE_ONLY
312 
313  } // end of namespace mln::util
314 
315 } // end of namespace mln
316 
317 
318 #endif // ! MLN_UTIL_TRACKED_PTR_HH