2 The STL+ C++ Library Collection
4 Website <http://stlplus.sourceforge.net/> Collection <index.html>
9 <http://www.opensource.org/>
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>
17 License for using the STLplus Library Collection
19 *© 1999-2008 Andy Rushton. All rights reserved.*
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions are met:
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
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.
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.
48 Modified version of STL+ sources shipped with the Mobile Robot
49 Programming Toolkit (MRPT).
51 Sources have been modified to support thred-safe smart pointers
52 through atomic operations.
54 2009, Jose Luis Blanco. University of Malaga.
57 #ifndef MRPT_SMARTPTR_H
58 #define MRPT_SMARTPTR_H
60 ////////////////////////////////////////////////////////////////////////////////
62 // Author: Andy Rushton
63 // Copyright: (c) Andy Rushton, 2007
64 // License: BSD License, see ../docs/license.html
66 ////////////////////////////////////////////////////////////////////////////////
71 ////////////////////////////////////////////////////////////////////////////////
72 // internal holder data structure
73 ////////////////////////////////////////////////////////////////////////////////
75 template<typename T,typename COUNTER>
76 class smart_ptr_holder
79 COUNTER m_count; //JL: It was... unsigned m_count;
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& ) :
88 inline smart_ptr_holder& operator=(const smart_ptr_holder& )
94 inline smart_ptr_holder(T* p = 0) :
99 ~smart_ptr_holder(void)
104 inline unsigned long count(void) const
109 inline void increment(void)
114 inline bool decrement(void)
116 return (--m_count)==0;
119 inline bool null(void)
124 inline void clear(void)
131 inline void set(T* p = 0)
137 inline T*& pointer(void)
142 inline const T* pointer(void) const
147 inline T& value(void)
152 inline const T& value(void) const
158 ////////////////////////////////////////////////////////////////////////////////
159 // smart_ptr_base class
160 ////////////////////////////////////////////////////////////////////////////////
162 ////////////////////////////////////////////////////////////////////////////////
163 // constructors, assignments and destructors
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>)
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>)
177 m_holder->set(C()(data));
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>)
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) :
195 m_holder = r.m_holder;
196 m_holder->increment();
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)
203 if(m_holder->decrement())
207 //////////////////////////////////////////////////////////////////////////////
208 // logical tests to see if there is anything contained in the pointer since it can be null
210 template <typename T, typename C, typename COUNTER>
211 inline bool smart_ptr_base<T,C,COUNTER>::null(void) const
213 return m_holder->null();
216 template <typename T, typename C, typename COUNTER>
217 inline bool smart_ptr_base<T,C,COUNTER>::present(void) const
219 return !m_holder->null();
222 template <typename T, typename C, typename COUNTER>
223 bool smart_ptr_base<T,C,COUNTER>::operator!(void) const
225 return m_holder->null();
228 template <typename T, typename C, typename COUNTER>
229 smart_ptr_base<T,C,COUNTER>::operator bool(void) const
231 return !m_holder->null();
234 //////////////////////////////////////////////////////////////////////////////
235 // dereference operators and functions
237 template <typename T, typename C, typename COUNTER>
238 inline T& smart_ptr_base<T,C,COUNTER>::operator*(void)
240 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
241 return m_holder->value();
244 template <typename T, typename C, typename COUNTER>
245 inline const T& smart_ptr_base<T,C,COUNTER>::operator*(void) const
247 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator*");
248 return m_holder->value();
251 template <typename T, typename C, typename COUNTER>
252 inline T* smart_ptr_base<T,C,COUNTER>::operator->(void)
254 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
255 return m_holder->pointer();
258 template <typename T, typename C, typename COUNTER>
259 inline const T* smart_ptr_base<T,C,COUNTER>::operator->(void) const
261 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::operator->");
262 return m_holder->pointer();
265 //////////////////////////////////////////////////////////////////////////////
266 // explicit function forms of the above assignment dereference operators
268 template <typename T, typename C, typename COUNTER>
269 inline void smart_ptr_base<T,C,COUNTER>::set_value(const T& data)
271 m_holder->set(C()(data));
274 template <typename T, typename C, typename COUNTER>
275 inline T& smart_ptr_base<T,C,COUNTER>::value(void)
277 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
278 return m_holder->value();
281 template <typename T, typename C, typename COUNTER>
282 inline const T& smart_ptr_base<T,C,COUNTER>::value(void) const
284 if (m_holder->null()) throw null_dereference("null pointer dereferenced in smart_ptr::value");
285 return m_holder->value();
288 template <typename T, typename C, typename COUNTER>
289 void smart_ptr_base<T,C,COUNTER>::set(T* data)
294 template <typename T, typename C, typename COUNTER>
295 inline T* smart_ptr_base<T,C,COUNTER>::pointer(void)
297 return m_holder->pointer();
300 template <typename T, typename C, typename COUNTER>
301 inline const T* smart_ptr_base<T,C,COUNTER>::pointer(void) const
303 return m_holder->pointer();
306 ////////////////////////////////////////////////////////////////////////////////
307 // functions to manage counted referencing
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)
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())
318 // m_holder = r.m_holder;
319 // m_holder->increment();
320 make_alias(r.m_holder);
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
326 return m_holder == r.m_holder;
329 template <typename T, typename C, typename COUNTER>
330 unsigned smart_ptr_base<T,C,COUNTER>::alias_count(void) const
332 return m_holder->count();
335 template <typename T, typename C, typename COUNTER>
336 void smart_ptr_base<T,C,COUNTER>::clear(void)
341 template <typename T, typename C, typename COUNTER>
342 void smart_ptr_base<T,C,COUNTER>::clear_unique(void)
344 if (m_holder->count() == 1)
348 m_holder->decrement();
350 m_holder = new smart_ptr_holder<T,COUNTER>;
354 template <typename T, typename C, typename COUNTER>
355 void smart_ptr_base<T,C,COUNTER>::make_unique(void)
357 if (m_holder->count() > 1)
359 smart_ptr_holder<T,COUNTER>* old_holder = m_holder;
360 m_holder->decrement();
362 m_holder = new smart_ptr_holder<T,COUNTER>;
363 if (old_holder->pointer())
364 m_holder->set(C()(old_holder->value()));
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)
375 // internal function for distinguishing unique smart_ptr objects
376 // used for example in persistence routines
378 template <typename T, typename C, typename COUNTER>
379 void* smart_ptr_base<T,C,COUNTER>::handle(void) const
384 template <typename T, typename C, typename COUNTER>
385 void smart_ptr_base<T,C,COUNTER>::make_alias(void* handle)
387 smart_ptr_holder<T,COUNTER>* r_holder = (smart_ptr_holder<T,COUNTER>*)handle;
388 if (m_holder != r_holder)
390 if (m_holder->decrement())
393 m_holder->increment();
397 ////////////////////////////////////////////////////////////////////////////////
399 } // end namespace stlplus