Main MRPT website
>
C++ reference
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
mrpt
otherlibs
stlplus
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
& s) :
84
m_count
(0),
m_data
(0)
85
{
86
}
87
88
inline
smart_ptr_holder
&
operator=
(
const
smart_ptr_holder
& s)
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.8.3
for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013