1//
2// RefPtr.h
3//
4// Library: Foundation
5// Package: Core
6// Module: RefPtr
7//
8// Definition of the RefPtr template class.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Foundation_RefPtr_INCLUDED
18#define Foundation_RefPtr_INCLUDED
19
20
21#include "Poco/Foundation.h"
22#include "Poco/Exception.h"
23
24
25namespace Poco {
26
27
28template <class C>
29class RefPtr
30 /// RefPtr is a "smart" pointer for classes implementing
31 /// reference counting based garbage collection.
32 /// To be usable with the RefPtr template, a class must
33 /// implement the following behaviour:
34 /// A class must maintain a reference count.
35 /// The constructors of the object initialize the reference
36 /// count to one.
37 /// The class must implement following public methods:
38 ///
39 /// void duplicate()
40 /// (increments the reference count by one)
41 ///
42 /// void release()
43 /// (decrements the reference count by one, if the reference
44 /// count reaches zero, deletes the object)
45 ///
46 /// For a conforming implementation, see RefCountedObject.
47 /// Unless there are specific reasons not to, it is recommended
48 /// that RefPtr-held objects inherit from RefCountedObject.
49 ///
50 /// RefPtr works in the following way:
51 /// If an RefPtr is assigned an ordinary pointer to
52 /// an object (via the constructor or the assignment operator),
53 /// it takes ownership of the object and the object's reference
54 /// count remains unchanged.
55 /// If the RefPtr is assigned another RefPtr, the
56 /// object's reference count is incremented by one by
57 /// calling duplicate() on its object.
58 /// The destructor of RefPtr calls release() on its
59 /// object.
60 /// RefPtr supports dereferencing with both the ->
61 /// and the * operator. An attempt to dereference a null
62 /// RefPtr results in a NullPointerException being thrown.
63 /// RefPtr also implements all relational operators.
64 /// Note that RefPtr allows casting of its encapsulated data types.
65 ///
66 /// RefPtr supports weak pointers to its internally held pointers.
67 /// For semantics, see WeakRefPtr documentation.
68 ///
69{
70public:
71 RefPtr(): _ptr(0)
72 {
73 }
74
75 RefPtr(C* ptr): _ptr(ptr)
76 {
77 }
78
79 RefPtr(C* ptr, bool shared): _ptr(ptr)
80 {
81 if (shared && _ptr) _ptr->duplicate();
82 }
83
84 RefPtr(const RefPtr& ptr): _ptr(ptr._ptr)
85 {
86 if (_ptr) _ptr->duplicate();
87 }
88
89 RefPtr(RefPtr&& ptr) : _ptr(ptr._ptr)
90 {
91 ptr._ptr = 0;
92 }
93
94 template <class Other>
95 RefPtr(const RefPtr<Other>& ptr): _ptr(const_cast<Other*>(ptr.get()))
96 {
97 if (_ptr) _ptr->duplicate();
98 }
99
100 template <class Other>
101 RefPtr(RefPtr<Other>&& ptr): _ptr(ptr.get())
102 {
103 ptr.resetMove();
104 }
105
106 ~RefPtr()
107 {
108 release();
109 }
110
111 RefPtr& assign(C* ptr)
112 {
113 if (_ptr != ptr)
114 {
115 release();
116 _ptr = ptr;
117 }
118 return *this;
119 }
120
121 RefPtr& assign(C* ptr, bool shared)
122 {
123 if (_ptr != ptr)
124 {
125 release();
126 _ptr = ptr;
127 if (shared && _ptr) _ptr->duplicate();
128 }
129 return *this;
130 }
131
132 RefPtr& assign(const RefPtr& ptr)
133 {
134 if (&ptr != this)
135 {
136 release();
137 _ptr = ptr._ptr;
138 if (_ptr) _ptr->duplicate();
139 }
140 return *this;
141 }
142
143 template <class Other>
144 RefPtr& assign(const RefPtr<Other>& ptr)
145 {
146 if (&ptr != (RefPtr<Other>*)this)
147 {
148 release();
149 _ptr = const_cast<Other*>(ptr.get());
150 if (_ptr) _ptr->duplicate();
151 }
152 return *this;
153 }
154
155 void resetMove()
156 {
157 if (_ptr) _ptr = 0;
158 }
159
160 void reset()
161 {
162 if (_ptr)
163 {
164 release();
165 _ptr = 0;
166 }
167 }
168
169 void reset(C* ptr)
170 {
171 assign(ptr);
172 }
173
174 void reset(C* ptr, bool shared)
175 {
176 assign(ptr, shared);
177 }
178
179 void reset(const RefPtr& ptr)
180 {
181 assign(ptr);
182 }
183
184 template <class Other>
185 void reset(const RefPtr<Other>& ptr)
186 {
187 assign<Other>(ptr);
188 }
189
190 RefPtr& operator = (C* ptr)
191 {
192 return assign(ptr);
193 }
194
195 RefPtr& operator = (const RefPtr& ptr)
196 {
197 return assign(ptr);
198 }
199
200 template <class Other>
201 RefPtr& operator = (const RefPtr<Other>& ptr)
202 {
203 return assign<Other>(ptr);
204 }
205
206 void moveAssign(C** pptr)
207 /// Move-assigns pointer to this RefPtr.
208 /// The pointer to pointer must not be null,
209 /// but the dereferenced pointer may be null.
210 /// Self move-assignment is no-op
211 {
212 poco_check_ptr (pptr);
213
214 if (*pptr != _ptr)
215 {
216 reset();
217 if (*pptr)
218 {
219 _ptr = *pptr;
220 *pptr = 0;
221 }
222 }
223 }
224
225 RefPtr& operator = (RefPtr&& refPtr)
226 {
227 moveAssign(&refPtr._ptr);
228 return *this;
229 }
230
231 template <class Other>
232 RefPtr& operator = (RefPtr<Other>&& otherRefPtr)
233 {
234 Other* pOther = otherRefPtr.get();
235 if (pOther != _ptr)
236 {
237 reset();
238 if (pOther)
239 {
240 _ptr = pOther;
241 otherRefPtr.resetMove();
242 }
243 }
244 return *this;
245 }
246
247 void swap(RefPtr& ptr)
248 {
249 std::swap(_ptr, ptr._ptr);
250 }
251
252 template <class Other>
253 RefPtr<Other> cast() const
254 /// Casts the RefPtr via a dynamic cast to the given type.
255 /// Returns an RefPtr containing NULL if the cast fails.
256 /// Example: (assume class Sub: public Super)
257 /// RefPtr<Super> super(new Sub());
258 /// RefPtr<Sub> sub = super.cast<Sub>();
259 /// poco_assert (sub.get());
260 {
261 return RefPtr<Other>(dynamic_cast<Other*>(_ptr), true);
262 }
263
264 template <class Other>
265 RefPtr<Other> unsafeCast() const
266 /// Casts the RefPtr via a static cast to the given type.
267 /// Example: (assume class Sub: public Super)
268 /// RefPtr<Super> super(new Sub());
269 /// RefPtr<Sub> sub = super.unsafeCast<Sub>();
270 /// poco_assert (sub.get());
271 {
272 return RefPtr<Other>(static_cast<Other*>(_ptr), true);
273 }
274
275 C* operator -> ()
276 {
277 if (_ptr)
278 return _ptr;
279 else
280 throw NullPointerException();
281 }
282
283 const C* operator -> () const
284 {
285 if (_ptr)
286 return _ptr;
287 else
288 throw NullPointerException();
289 }
290
291 C& operator * ()
292 {
293 if (_ptr)
294 return *_ptr;
295 else
296 throw NullPointerException();
297 }
298
299 const C& operator * () const
300 {
301 if (_ptr)
302 return *_ptr;
303 else
304 throw NullPointerException();
305 }
306
307 C* get()
308 {
309 return _ptr;
310 }
311
312 const C* get() const
313 {
314 return _ptr;
315 }
316
317 operator C* ()
318 {
319 return _ptr;
320 }
321
322 operator const C* () const
323 {
324 return _ptr;
325 }
326
327 bool operator ! () const
328 {
329 return _ptr == 0;
330 }
331
332 bool isNull() const
333 {
334 return _ptr == 0;
335 }
336
337 C* duplicate()
338 {
339 if (_ptr) _ptr->duplicate();
340 return _ptr;
341 }
342
343 bool operator == (const RefPtr& ptr) const
344 {
345 return _ptr == ptr._ptr;
346 }
347
348 bool operator == (const C* ptr) const
349 {
350 return _ptr == ptr;
351 }
352
353 bool operator == (C* ptr) const
354 {
355 return _ptr == ptr;
356 }
357
358 bool operator != (const RefPtr& ptr) const
359 {
360 return _ptr != ptr._ptr;
361 }
362
363 bool operator != (const C* ptr) const
364 {
365 return _ptr != ptr;
366 }
367
368 bool operator != (C* ptr) const
369 {
370 return _ptr != ptr;
371 }
372
373 bool operator < (const RefPtr& ptr) const
374 {
375 return _ptr < ptr._ptr;
376 }
377
378 bool operator < (const C* ptr) const
379 {
380 return _ptr < ptr;
381 }
382
383 bool operator < (C* ptr) const
384 {
385 return _ptr < ptr;
386 }
387
388 bool operator <= (const RefPtr& ptr) const
389 {
390 return _ptr <= ptr._ptr;
391 }
392
393 bool operator <= (const C* ptr) const
394 {
395 return _ptr <= ptr;
396 }
397
398 bool operator <= (C* ptr) const
399 {
400 return _ptr <= ptr;
401 }
402
403 bool operator > (const RefPtr& ptr) const
404 {
405 return _ptr > ptr._ptr;
406 }
407
408 bool operator > (const C* ptr) const
409 {
410 return _ptr > ptr;
411 }
412
413 bool operator > (C* ptr) const
414 {
415 return _ptr > ptr;
416 }
417
418 bool operator >= (const RefPtr& ptr) const
419 {
420 return _ptr >= ptr._ptr;
421 }
422
423 bool operator >= (const C* ptr) const
424 {
425 return _ptr >= ptr;
426 }
427
428 bool operator >= (C* ptr) const
429 {
430 return _ptr >= ptr;
431 }
432
433private:
434 void release()
435 {
436 if (_ptr) _ptr->release();
437 }
438
439 C* _ptr = 0;
440};
441
442
443template <class C>
444inline void swap(RefPtr<C>& p1, RefPtr<C>& p2)
445{
446 p1.swap(p2);
447}
448
449
450} // namespace Poco
451
452
453#endif // Foundation_RefPtr_INCLUDED
454