Main MRPT website > C++ reference for MRPT 1.5.3
smart_ptr.tpp
Go to the documentation of this file.
1 /*
2  The STL+ C++ Library Collection
3 
4  Website <http://stlplus.sourceforge.net/> Collection <index.html>
5 
6 
7  License Agreement
8 
9  <http://www.opensource.org/>
10 
11  * License for using the STLplus Library Collection <#license>
12  * The Intent of this License <#intent>
13  * How to Comply with this License <#compliance>
14  * Historical Note <#history>
15 
16 
17  License for using the STLplus Library Collection
18 
19  *© 1999-2008 Andy Rushton. All rights reserved.*
20 
21  Redistribution and use in source and binary forms, with or without
22  modification, are permitted provided that the following conditions are met:
23 
24  * Redistributions of source code must retain the above Copyright
25  notice, this list of conditions and the following disclaimer.
26  * Redistributions in binary form must reproduce the above Copyright
27  notice, this list of conditions and the following disclaimer in
28  the documentation and/or other materials provided with the
29  distribution.
30  * Neither the name of the STLplus library nor the names of its
31  contributors may be used to endorse or promote products derived
32  from this software without specific prior written permission.
33 
34  This software is provided by the Copyright holders and contributors "as
35  is" and any express or implied warranties, including, but not limited
36  to, the implied warranties of merchantability and fitness for a
37  particular purpose are disclaimed. In no event shall the Copyright owner
38  or contributors be liable for any direct, indirect, incidental, special,
39  exemplary, or consequential damages (including, but not limited to,
40  procurement of substitute goods or services; loss of use, data, or
41  profits; or business interruption) however caused and on any theory of
42  liability, whether in contract, strict liability, or tort (including
43  negligence or otherwise) arising in any way out of the use of this
44  software, even if advised of the possibility of such damage.
45 */
46 
47 /*
48  Modified version of STL+ sources shipped with the Mobile Robot
49  Programming Toolkit (MRPT).
50 
51  Sources have been modified to support thred-safe smart pointers
52  through atomic operations.
53 
54  2009, Jose Luis Blanco. University of Malaga.
55 */
56 
57 #ifndef MRPT_SMARTPTR_H
58 #define MRPT_SMARTPTR_H
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 
62 // Author: Andy Rushton
63 // Copyright: (c) Andy Rushton, 2007
64 // License: BSD License, see ../docs/license.html
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 
68 namespace stlplus
69 {
70 
71  ////////////////////////////////////////////////////////////////////////////////
72  // internal holder data structure
73  ////////////////////////////////////////////////////////////////////////////////
74 
75  template<typename T,typename COUNTER>
76  class smart_ptr_holder
77  {
78  private:
79  COUNTER m_count; //JL: It was... unsigned m_count;
80  T* m_data;
81 
82  // make these private to disallow copying because the holder doesn't know how to copy
83  inline smart_ptr_holder(const smart_ptr_holder& ) :
84  m_count(0), m_data(0)
85  {
86  }
87 
88  inline smart_ptr_holder& operator=(const smart_ptr_holder& )
89  {
90  return *this;
91  }
92 
93  public:
94  inline smart_ptr_holder(T* p = 0) :
95  m_count(1), m_data(p)
96  {
97  }
98 
99  ~smart_ptr_holder(void)
100  {
101  clear();
102  }
103 
104  inline unsigned long count(void) const
105  {
106  return m_count;
107  }
108 
109  inline void increment(void)
110  {
111  ++m_count;
112  }
113 
114  inline bool decrement(void)
115  {
116  return (--m_count)==0;
117  }
118 
119  inline bool null(void)
120  {
121  return m_data == 0;
122  }
123 
124  inline void clear(void)
125  {
126  if(m_data)
127  delete m_data;
128  m_data = 0;
129  }
130 
131  inline void set(T* p = 0)
132  {
133  clear();
134  m_data = p;
135  }
136 
137  inline T*& pointer(void)
138  {
139  return m_data;
140  }
141 
142  inline const T* pointer(void) const
143  {
144  return m_data;
145  }
146 
147  inline T& value(void)
148  {
149  return *m_data;
150  }
151 
152  inline const T& value(void) const
153  {
154  return *m_data;
155  }
156  };
157 
158  ////////////////////////////////////////////////////////////////////////////////
159  // smart_ptr_base class
160  ////////////////////////////////////////////////////////////////////////////////
161 
162  ////////////////////////////////////////////////////////////////////////////////
163  // constructors, assignments and destructors
164 
165  // create a null pointer
166  template <typename T, typename C, typename COUNTER>
167  smart_ptr_base<T,C,COUNTER>::smart_ptr_base(void) :
168  m_holder(new smart_ptr_holder<T,COUNTER>)
169  {
170  }
171 
172  // create a pointer containing a *copy* of the object pointer
173  template <typename T, typename C, typename COUNTER>
174  smart_ptr_base<T,C,COUNTER>::smart_ptr_base(const T& data) :
175  m_holder(new smart_ptr_holder<T,COUNTER>)
176  {
177  m_holder->set(C()(data));
178  }
179 
180  // create a pointer containing a dynamically created object
181  // Note: the object must be allocated *by the user* with new
182  // constructor form - must be called in the form smart_ptr<type> x(new type(args))
183  template <typename T, typename C, typename COUNTER>
184  smart_ptr_base<T,C,COUNTER>::smart_ptr_base(T* data) :
185  m_holder(new smart_ptr_holder<T,COUNTER>)
186  {
187  m_holder->set(data);
188  }
189 
190  // copy constructor implements counted referencing - no copy is made
191  template <typename T, typename C, typename COUNTER>
192  smart_ptr_base<T,C,COUNTER>::smart_ptr_base(const smart_ptr_base<T,C,COUNTER>& r) :
193  m_holder(0)
194  {
195  m_holder = r.m_holder;
196  m_holder->increment();
197  }
198 
199  // destructor decrements the reference count and delete only when the last reference is destroyed
200  template <typename T, typename C, typename COUNTER>
201  smart_ptr_base<T,C,COUNTER>::~smart_ptr_base(void)
202  {
203  if(m_holder->decrement())
204  delete m_holder;
205  }
206 
207  //////////////////////////////////////////////////////////////////////////////
208  // logical tests to see if there is anything contained in the pointer since it can be null
209 
210  template <typename T, typename C, typename COUNTER>
211  inline bool smart_ptr_base<T,C,COUNTER>::null(void) const
212  {
213  return m_holder->null();
214  }
215 
216  template <typename T, typename C, typename COUNTER>
217  inline bool smart_ptr_base<T,C,COUNTER>::present(void) const
218  {
219  return !m_holder->null();
220  }
221 
222  template <typename T, typename C, typename COUNTER>
223  bool smart_ptr_base<T,C,COUNTER>::operator!(void) const
224  {
225  return m_holder->null();
226  }
227 
228  template <typename T, typename C, typename COUNTER>
229  smart_ptr_base<T,C,COUNTER>::operator bool(void) const
230  {
231  return !m_holder->null();
232  }
233 
234  //////////////////////////////////////////////////////////////////////////////
235  // dereference operators and functions
236 
237  template <typename T, typename C, typename COUNTER>
238  inline T& smart_ptr_base<T,C,COUNTER>::operator*(void)
239  {
240  if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
241  return m_holder->value();
242  }
243 
244  template <typename T, typename C, typename COUNTER>
245  inline const T& smart_ptr_base<T,C,COUNTER>::operator*(void) const
246  {
247  if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
248  return m_holder->value();
249  }
250 
251  template <typename T, typename C, typename COUNTER>
252  inline T* smart_ptr_base<T,C,COUNTER>::operator->(void)
253  {
254  if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
255  return m_holder->pointer();
256  }
257 
258  template <typename T, typename C, typename COUNTER>
259  inline const T* smart_ptr_base<T,C,COUNTER>::operator->(void) const
260  {
261  if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
262  return m_holder->pointer();
263  }
264 
265  //////////////////////////////////////////////////////////////////////////////
266  // explicit function forms of the above assignment dereference operators
267 
268  template <typename T, typename C, typename COUNTER>
269  inline void smart_ptr_base<T,C,COUNTER>::set_value(const T& data)
270  {
271  m_holder->set(C()(data));
272  }
273 
274  template <typename T, typename C, typename COUNTER>
275  inline T& smart_ptr_base<T,C,COUNTER>::value(void)
276  {
277  if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
278  return m_holder->value();
279  }
280 
281  template <typename T, typename C, typename COUNTER>
282  inline const T& smart_ptr_base<T,C,COUNTER>::value(void) const
283  {
284  if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
285  return m_holder->value();
286  }
287 
288  template <typename T, typename C, typename COUNTER>
289  void smart_ptr_base<T,C,COUNTER>::set(T* data)
290  {
291  m_holder->set(data);
292  }
293 
294  template <typename T, typename C, typename COUNTER>
295  inline T* smart_ptr_base<T,C,COUNTER>::pointer(void)
296  {
297  return m_holder->pointer();
298  }
299 
300  template <typename T, typename C, typename COUNTER>
301  inline const T* smart_ptr_base<T,C,COUNTER>::pointer(void) const
302  {
303  return m_holder->pointer();
304  }
305 
306  ////////////////////////////////////////////////////////////////////////////////
307  // functions to manage counted referencing
308 
309  // make this an alias of the passed object
310  template <typename T, typename C, typename COUNTER>
311  void smart_ptr_base<T,C,COUNTER>::alias(const smart_ptr_base<T,C,COUNTER>& r)
312  {
313  // make it alias-copy safe - this means that I don't try to do the
314  // assignment if r is either the same object or an alias of it
315  // if (m_holder == r.m_holder) return;
316  // if (m_holder->decrement())
317  // delete m_holder;
318  // m_holder = r.m_holder;
319  // m_holder->increment();
320  make_alias(r.m_holder);
321  }
322 
323  template <typename T, typename C, typename COUNTER>
324  bool smart_ptr_base<T,C,COUNTER>::aliases(const smart_ptr_base<T,C,COUNTER>& r) const
325  {
326  return m_holder == r.m_holder;
327  }
328 
329  template <typename T, typename C, typename COUNTER>
330  unsigned smart_ptr_base<T,C,COUNTER>::alias_count(void) const
331  {
332  return m_holder->count();
333  }
334 
335  template <typename T, typename C, typename COUNTER>
336  void smart_ptr_base<T,C,COUNTER>::clear(void)
337  {
338  m_holder->clear();
339  }
340 
341  template <typename T, typename C, typename COUNTER>
342  void smart_ptr_base<T,C,COUNTER>::clear_unique(void)
343  {
344  if (m_holder->count() == 1)
345  m_holder->clear();
346  else
347  {
348  m_holder->decrement();
349  m_holder = 0;
350  m_holder = new smart_ptr_holder<T,COUNTER>;
351  }
352  }
353 
354  template <typename T, typename C, typename COUNTER>
355  void smart_ptr_base<T,C,COUNTER>::make_unique(void)
356  {
357  if (m_holder->count() > 1)
358  {
359  smart_ptr_holder<T,COUNTER>* old_holder = m_holder;
360  m_holder->decrement();
361  m_holder = 0;
362  m_holder = new smart_ptr_holder<T,COUNTER>;
363  if (old_holder->pointer())
364  m_holder->set(C()(old_holder->value()));
365  }
366  }
367 
368  template <typename T, typename C, typename COUNTER>
369  void smart_ptr_base<T,C,COUNTER>::copy(const smart_ptr_base<T,C,COUNTER>& data)
370  {
371  alias(data);
372  make_unique();
373  }
374 
375  // internal function for distinguishing unique smart_ptr objects
376  // used for example in persistence routines
377 
378  template <typename T, typename C, typename COUNTER>
379  void* smart_ptr_base<T,C,COUNTER>::handle(void) const
380  {
381  return m_holder;
382  }
383 
384  template <typename T, typename C, typename COUNTER>
385  void smart_ptr_base<T,C,COUNTER>::make_alias(void* handle)
386  {
387  smart_ptr_holder<T,COUNTER>* r_holder = (smart_ptr_holder<T,COUNTER>*)handle;
388  if (m_holder != r_holder)
389  {
390  if (m_holder->decrement())
391  delete m_holder;
392  m_holder = r_holder;
393  m_holder->increment();
394  }
395  }
396 
397  ////////////////////////////////////////////////////////////////////////////////
398 
399 } // end namespace stlplus
400 
401 #endif



Page generated by Doxygen 1.8.13 for MRPT 1.5.3 at Mon Oct 30 10:27:08 UTC 2017