Main MRPT website > C++ reference for MRPT 1.4.0
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
68namespace 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) throw(illegal_copy) :
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) throw(null_dereference)
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 throw(null_dereference)
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) throw(null_dereference)
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 throw(null_dereference)
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) throw(illegal_copy)
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) throw(null_dereference)
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 throw(null_dereference)
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) throw(illegal_copy)
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) throw(illegal_copy)
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
402



Page generated by Doxygen 1.9.5 for MRPT 1.4.0 SVN: at Sun Dec 25 21:25:12 UTC 2022