Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
tracked_ptr.hh
1 // Copyright (C) 2006, 2007, 2008, 2009 EPITA Research and Development
2 // 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  {
54  typedef tracked_ptr<T> self_t;
55  typedef std::set<self_t*> holders_t;
56 
57  T* ptr_;
58  holders_t* holders_;
59 
61  operator bool() const;
62 
64  bool operator !() const;
65 
69  const T* operator->() const;
70 
74  T* operator->();
75 
78  tracked_ptr();
79  tracked_ptr(T* ptr);
81  tracked_ptr(const tracked_ptr<T>& rhs);
83 
86 
88  tracked_ptr<T>& operator=(T* ptr);
89 
91  ~tracked_ptr();
92 
93  bool run_() const;
94 
95  void clean_();
96 
97  };
98 
99 
100 
101 
102 # ifndef MLN_INCLUDE_ONLY
103 
104  template <typename T>
105  inline
107  {
108  mln_invariant(run_());
109  return ptr_ != 0;
110  }
111 
112  template <typename T>
113  inline
115  {
116  mln_invariant(run_());
117  return ! bool(*this);
118  }
119 
120  template <typename T>
121  inline
122  const T* tracked_ptr<T>::operator->() const
123  {
124  mln_invariant(run_());
125  mln_precondition(ptr_ != 0);
126  return ptr_;
127  }
128 
129  template <typename T>
130  inline
132  {
133  mln_invariant(run_());
134  mln_precondition(ptr_ != 0);
135  return ptr_;
136  }
137 
138  template <typename T>
139  inline
141  ptr_(0),
142  holders_(0)
143  {
144  mln_invariant(run_());
145  }
146 
147  template <typename T>
148  inline
150  ptr_(ptr)
151  {
152  if (ptr == 0)
153  holders_ = 0;
154  else
155  {
156  holders_ = new holders_t;
157  holders_->insert(this);
158  }
159  mln_invariant(run_());
160  }
161 
162  template <typename T>
163  inline
165  ptr_(rhs.ptr_),
166  holders_(rhs.holders_)
167  {
168  mln_invariant(rhs.run_());
169  if (ptr_ != 0)
170  holders_->insert(this);
171  mln_invariant(run_());
172  }
173 
174  template <typename T>
175  inline
177  {
178  mln_invariant(run_());
179  mln_invariant(rhs.run_());
180  if (&rhs == this || rhs.ptr_ == ptr_)
181  // no-op
182  return *this;
183  clean_();
184  ptr_ = rhs.ptr_;
185  holders_ = rhs.holders_;
186  // If ptr == 0, holders_ == 0 so we cannot insert anything in it.
187  if (holders_ != 0)
188  holders_->insert(this);
189  mln_invariant(run_());
190  return *this;
191  }
192 
193  template <typename T>
194  inline
196  {
197  mln_invariant(run_());
198  if (ptr == ptr_)
199  // no-op
200  return *this;
201  clean_();
202  ptr_ = ptr;
203  if (ptr == 0)
204  holders_ = 0;
205  else
206  {
207  holders_ = new holders_t;
208  holders_->insert(this);
209  }
210  mln_invariant(run_());
211  return *this;
212  }
213 
214  template <typename T>
215  inline
217  {
218  clean_();
219  }
220 
221  template <typename T>
222  inline
223  bool tracked_ptr<T>::run_() const
224  {
225  mln_invariant((ptr_ && holders_) || (! ptr_ && ! holders_));
226  if (ptr_ == 0)
227  return true;
228  mln_invariant(holders_->size() > 0);
229  tracked_ptr<T>* this_ = const_cast<tracked_ptr<T>*>(this);
230  mln_invariant(holders_->find(this_) != holders_->end());
231  this_ = 0;
232  typename holders_t::const_iterator i;
233  for (i = holders_->begin(); i != holders_->end(); ++i)
234  mln_invariant((*i)->ptr_ == ptr_);
235  return true;
236  }
237 
238  template <typename T>
239  inline
240  void tracked_ptr<T>::clean_()
241  {
242  mln_invariant(run_());
243  if (ptr_ == 0)
244  // no-op
245  return;
246  if (holders_->size() == 1)
247  {
248  delete ptr_;
249  delete holders_;
250  }
251  else
252  holders_->erase(this);
253  ptr_ = 0;
254  holders_ = 0;
255  mln_invariant(run_());
256  }
257 
258  template <typename T>
259  inline
260  std::ostream& operator<<(std::ostream& ostr, const tracked_ptr<T>& tp)
261  {
262  typedef std::set<tracked_ptr<T>*> holders_t;
263 
264  mln_invariant(tp.run_());
265  ostr << "tracked_ptr @ " << (&tp)
266  << " { ptr = " << tp.ptr_
267  << " / holders = ";
268  if (tp.holders_ == 0)
269  ostr << "0";
270  else
271  {
272  typename holders_t::const_iterator i;
273  for (i = tp.holders_->begin(); i != tp.holders_->end(); ++i)
274  ostr << (*i) << ' ';
275  }
276  ostr << " }";
277  return ostr;
278  }
279 
280 
281 # endif // ! MLN_INCLUDE_ONLY
282 
283  } // end of namespace mln::util
284 
285 } // end of namespace mln
286 
287 
288 #endif // ! MLN_UTIL_TRACKED_PTR_HH