Fawkes API Fawkes Development Version
refptr.h
1
2/***************************************************************************
3 * refptr.h - reference counting shared smartpointer
4 *
5 * Created: Sat Jan 24 12:29:41 2009
6 * Copyright 2002 The gtkmm Development Team
7 * 2005 The cairomm Development Team
8 * 2009 Tim Niemueller [www.niemueller.de]
9 *
10 ****************************************************************************/
11
12/* This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version. A runtime exception applies to
16 * this software (see LICENSE.GPL_WRE file mentioned below for details).
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Library General Public License for more details.
22 *
23 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
24 */
25
26#ifndef _CORE_UTILS_REFPTR_H_
27#define _CORE_UTILS_REFPTR_H_
28
29#include <core/threading/mutex.h>
30
31namespace fawkes {
32
33/** RefPtr<> is a reference-counting shared smartpointer.
34 *
35 * Reference counting means that a shared reference count is incremented each
36 * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
37 * for instance when it leaves its scope. When the reference count reaches
38 * zero, the contained object is deleted
39 *
40 * Fawkes uses RefPtr so that you don't need to remember
41 * to delete the object explicitly, or know when a method expects you to delete
42 * the object that it returns.
43 *
44 * Note that RefPtr is thread-safe.
45 *
46 * @ingroup FCL
47 */
48template <class T_CppObject>
49class RefPtr
50{
51public:
52 /** Default constructor
53 *
54 * Afterwards it will be null and use of -> will cause a segmentation fault.
55 */
56 inline RefPtr();
57
58 /// Destructor - decrements reference count.
59 inline ~RefPtr();
60
61 /** Constructor that takes ownership.
62 *
63 * This takes ownership of @a cpp_object, so it will be deleted when the
64 * last RefPtr is deleted, for instance when it goes out of scope.
65 * @param cpp_object C++ object to take ownership of
66 */
67 explicit inline RefPtr(T_CppObject *cpp_object);
68
69 /** Copy constructor
70 * This increments the shared reference count.
71 * @param src refptr to copy
72 */
73 inline RefPtr(const RefPtr<T_CppObject> &src);
74
75 /** Copy constructor (from different, but castable type).
76 * Increments the reference count.
77 * @param src refptr to copy
78 */
79 template <class T_CastFrom>
80 inline RefPtr(const RefPtr<T_CastFrom> &src);
81
82 /** Swap the contents of two RefPtr<>.
83 * This method swaps the internal pointers to T_CppObject. This can be
84 * done safely without involving a reference/unreference cycle and is
85 * therefore highly efficient.
86 * @param other other instance to swap with.
87 */
88 inline void swap(RefPtr<T_CppObject> &other);
89
90 /** Copy from another RefPtr.
91 * @param src refptr to copy from
92 * @return reference to this instance
93 */
95
96 /** Copy from different, but castable type).
97 * Increments the reference count.
98 * @param src refptr to copy from
99 * @return reference to this instance
100 */
101 template <class T_CastFrom>
103
104 /** Assign object and claim ownership.
105 * @param ptr pointer to object, this refptr will claim ownership of the src!
106 * @return reference to this instance
107 */
108 inline RefPtr<T_CppObject> &operator=(T_CppObject *ptr);
109
110 /** Tests whether the RefPtr<> point to the same underlying instance.
111 * @param src refptr to compare to
112 * @return true if both refptrs point to the same instance.
113 */
114 inline bool operator==(const RefPtr<T_CppObject> &src) const;
115
116 /** Tests whether the RefPtr<> do not point to the same underlying instance.
117 * @param src refptr to compare to
118 * @return true if both refptrs do not point to the same instance.
119 */
120 inline bool operator!=(const RefPtr<T_CppObject> &src) const;
121
122 /** Dereferencing.
123 * Use the methods of the underlying instance like so:
124 * <code>refptr->memberfun()</code>.
125 * @return pointer to encapsulated object
126 */
127 inline T_CppObject *operator->() const;
128
129 /** Get underlying pointer.
130 * Use with care!
131 * @return pointer to encapsulated object
132 */
133 inline T_CppObject *operator*() const;
134
135 /** Test whether the RefPtr<> points to any underlying instance.
136 *
137 * Mimics usage of ordinary pointers:
138 * @code
139 * if (ptr)
140 * do_something();
141 * @endcode
142 */
143 inline operator bool() const;
144
145 /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
146 inline void clear();
147
148 /** Reset pointer.
149 * Set underlying instance to 0, decrementing reference count of
150 * existing instance appropriately.
151 */
152 inline void reset();
153
154 /** Dynamic cast to derived class.
155 *
156 * The RefPtr can't be cast with the usual notation so instead you can use
157 * @code
158 * ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
159 * @endcode
160 * @param src source refptr to cast
161 * @return refptr to object casted to given type
162 */
163 template <class T_CastFrom>
164 static inline RefPtr<T_CppObject>
166 {
167 T_CppObject *const cpp_object = dynamic_cast<T_CppObject *>(src.operator->());
168
169 if (
170 cpp_object) //Check whether dynamic_cast<> succeeded so we don't pass a null object with a used refcount:
171 return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
172 else
173 return RefPtr<T_CppObject>();
174 }
175
176 /** Static cast to derived class.
177 *
178 * Like the dynamic cast; the notation is
179 * @code
180 * ptr_derived = RefPtr<Derived>::cast_static(ptr_base);
181 * @endcode
182 * @param src source refptr to cast
183 * @return refptr to object casted to given type
184 */
185 template <class T_CastFrom>
186 static inline RefPtr<T_CppObject>
188 {
189 T_CppObject *const cpp_object = static_cast<T_CppObject *>(src.operator->());
190
191 return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
192 }
193
194 /** Cast to non-const.
195 *
196 * The RefPtr can't be cast with the usual notation so instead you can use
197 * @code
198 * ptr_unconst = RefPtr<UnConstType>::cast_const(ptr_const);
199 * @endcode
200 * @param src source refptr to cast
201 * @return refptr to object casted to given type
202 */
203 template <class T_CastFrom>
204 static inline RefPtr<T_CppObject>
206 {
207 T_CppObject *const cpp_object = const_cast<T_CppObject *>(src.operator->());
208
209 return RefPtr<T_CppObject>(cpp_object, src.refcount_ptr(), src.refmutex_ptr());
210 }
211
212 /** For use only in the internal implementation of sharedptr.
213 * @param cpp_object C++ object to wrap
214 * @param refcount reference count
215 * @param refmutex reference count mutex
216 */
217 explicit inline RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex);
218
219 /** For use only in the internal implementation of sharedptr.
220 * Get reference count pointer.
221 * Warning: This is for internal use only. Do not manually modify the
222 * reference count with this pointer.
223 * @return pointer to refcount integer
224 */
225 inline int *
227 {
228 return ref_count_;
229 }
230
231 /** Get current reference count.
232 * @return current number of owners referencing this RefPtr.
233 */
234 inline int
235 use_count() const
236 {
237 return *ref_count_;
238 }
239
240 /** For use only in the internal implementation of sharedptr.
241 * Get reference mutex.
242 * @return pointer to refcount mutex
243 */
244 inline Mutex *
246 {
247 return ref_mutex_;
248 }
249
250private:
251 T_CppObject * cpp_object_;
252 mutable int * ref_count_;
253 mutable Mutex *ref_mutex_;
254};
255
256// RefPtr<>::operator->() comes first here since it's used by other methods.
257// If it would come after them it wouldn't be inlined.
258
259template <class T_CppObject>
260inline T_CppObject *
262{
263 return cpp_object_;
264}
265
266template <class T_CppObject>
267inline T_CppObject *
269{
270 return cpp_object_;
271}
272
273template <class T_CppObject>
274inline RefPtr<T_CppObject>::RefPtr() : cpp_object_(0), ref_count_(0), ref_mutex_(0)
275{
276}
277
278template <class T_CppObject>
280{
281 if (ref_count_ && ref_mutex_) {
282 ref_mutex_->lock();
283
284 --(*ref_count_);
285
286 if (*ref_count_ == 0) {
287 if (cpp_object_) {
288 delete cpp_object_;
289 cpp_object_ = 0;
290 }
291
292 delete ref_count_;
293 delete ref_mutex_;
294 ref_count_ = 0;
295 ref_mutex_ = 0;
296 } else {
297 ref_mutex_->unlock();
298 }
299 }
300}
301
302template <class T_CppObject>
303inline RefPtr<T_CppObject>::RefPtr(T_CppObject *cpp_object)
304: cpp_object_(cpp_object), ref_count_(0), ref_mutex_(0)
305{
306 if (cpp_object) {
307 ref_count_ = new int;
308 ref_mutex_ = new Mutex();
309 *ref_count_ = 1; //This will be decremented in the destructor.
310 }
311}
312
313//Used by cast_*() implementations:
314template <class T_CppObject>
315inline RefPtr<T_CppObject>::RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex)
316: cpp_object_(cpp_object), ref_count_(refcount), ref_mutex_(refmutex)
317{
318 if (cpp_object_ && ref_count_ && ref_mutex_) {
319 ref_mutex_->lock();
320 ++(*ref_count_);
321 ref_mutex_->unlock();
322 }
323}
324
325template <class T_CppObject>
327: cpp_object_(src.cpp_object_), ref_count_(src.ref_count_), ref_mutex_(src.ref_mutex_)
328{
329 if (cpp_object_ && ref_count_ && ref_mutex_) {
330 ref_mutex_->lock();
331 ++(*ref_count_);
332 ref_mutex_->unlock();
333 }
334}
335
336// The templated ctor allows copy construction from any object that's
337// castable. Thus, it does downcasts:
338// base_ref = derived_ref
339template <class T_CppObject>
340template <class T_CastFrom>
342: // A different RefPtr<> will not allow us access to cpp_object_. We need
343 // to add a get_underlying() for this, but that would encourage incorrect
344 // use, so we use the less well-known operator->() accessor:
345 cpp_object_(src.operator->()),
346 ref_count_(src.refcount_ptr()),
347 ref_mutex_(src.refmutex_ptr())
348{
349 if (cpp_object_ && ref_count_ && ref_mutex_) {
350 ref_mutex_->lock();
351 ++(*ref_count_);
352 ref_mutex_->unlock();
353 }
354}
355
356template <class T_CppObject>
357inline void
359{
360 T_CppObject *const temp = cpp_object_;
361 int * temp_count = ref_count_;
362 Mutex * temp_mutex = ref_mutex_;
363
364 cpp_object_ = other.cpp_object_;
365 ref_count_ = other.ref_count_;
366 ref_mutex_ = other.ref_mutex_;
367
368 other.cpp_object_ = temp;
369 other.ref_count_ = temp_count;
370 other.ref_mutex_ = temp_mutex;
371}
372
373template <class T_CppObject>
374inline RefPtr<T_CppObject> &
376{
377 // In case you haven't seen the swap() technique to implement copy
378 // assignment before, here's what it does:
379 //
380 // 1) Create a temporary RefPtr<> instance via the copy ctor, thereby
381 // increasing the reference count of the source object.
382 //
383 // 2) Swap the internal object pointers of *this and the temporary
384 // RefPtr<>. After this step, *this already contains the new pointer,
385 // and the old pointer is now managed by temp.
386 //
387 // 3) The destructor of temp is executed, thereby unreferencing the
388 // old object pointer.
389 //
390 // This technique is described in Herb Sutter's "Exceptional C++", and
391 // has a number of advantages over conventional approaches:
392 //
393 // - Code reuse by calling the copy ctor.
394 // - Strong exception safety for free.
395 // - Self assignment is handled implicitely.
396 // - Simplicity.
397 // - It just works and is hard to get wrong; i.e. you can use it without
398 // even thinking about it to implement copy assignment whereever the
399 // object data is managed indirectly via a pointer, which is very common.
400
401 RefPtr<T_CppObject> temp(src);
402 this->swap(temp);
403 return *this;
404}
405
406template <class T_CppObject>
407inline RefPtr<T_CppObject> &
409{
410 RefPtr<T_CppObject> temp(ptr);
411 this->swap(temp);
412 return *this;
413}
414
415template <class T_CppObject>
416template <class T_CastFrom>
417inline RefPtr<T_CppObject> &
419{
420 RefPtr<T_CppObject> temp(src);
421 this->swap(temp);
422 return *this;
423}
424
425template <class T_CppObject>
426inline bool
428{
429 return (cpp_object_ == src.cpp_object_);
430}
431
432template <class T_CppObject>
433inline bool
435{
436 return (cpp_object_ != src.cpp_object_);
437}
438
439template <class T_CppObject>
441{
442 return (cpp_object_ != 0);
443}
444
445template <class T_CppObject>
446inline void
448{
449 RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
450 this->swap(temp);
451}
452
453template <class T_CppObject>
454inline void
456{
457 RefPtr<T_CppObject> temp; // swap with an empty RefPtr<> to clear *this
458 this->swap(temp);
459}
460
461/** Swap refptr instances.
462 * @param lrp "left" refptr
463 * @param rrp "right" refptr
464 * @relates fawkes::RefPtr
465 */
466template <class T_CppObject>
467inline void
469{
470 lrp.swap(rrp);
471}
472
473} // end namespace fawkes
474
475#endif
Mutex mutual exclusion lock.
Definition: mutex.h:33
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:50
RefPtr< T_CppObject > & operator=(const RefPtr< T_CppObject > &src)
Copy from another RefPtr.
Definition: refptr.h:375
void clear()
Set underlying instance to 0, decrementing reference count of existing instance appropriately.
Definition: refptr.h:447
Mutex * refmutex_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:245
static RefPtr< T_CppObject > cast_dynamic(const RefPtr< T_CastFrom > &src)
Dynamic cast to derived class.
Definition: refptr.h:165
T_CppObject * operator*() const
Get underlying pointer.
Definition: refptr.h:268
void swap(RefPtr< T_CppObject > &lrp, RefPtr< T_CppObject > &rrp)
Swap refptr instances.
Definition: refptr.h:468
int * refcount_ptr() const
For use only in the internal implementation of sharedptr.
Definition: refptr.h:226
bool operator!=(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> do not point to the same underlying instance.
Definition: refptr.h:434
RefPtr(const RefPtr< T_CppObject > &src)
Copy constructor This increments the shared reference count.
Definition: refptr.h:326
RefPtr()
Default constructor.
Definition: refptr.h:274
RefPtr(T_CppObject *cpp_object)
Constructor that takes ownership.
Definition: refptr.h:303
static RefPtr< T_CppObject > cast_static(const RefPtr< T_CastFrom > &src)
Static cast to derived class.
Definition: refptr.h:187
void reset()
Reset pointer.
Definition: refptr.h:455
RefPtr< T_CppObject > & operator=(const RefPtr< T_CastFrom > &src)
Copy from different, but castable type).
Definition: refptr.h:418
~RefPtr()
Destructor - decrements reference count.
Definition: refptr.h:279
RefPtr(const RefPtr< T_CastFrom > &src)
Copy constructor (from different, but castable type).
Definition: refptr.h:341
T_CppObject * operator->() const
Dereferencing.
Definition: refptr.h:261
int use_count() const
Get current reference count.
Definition: refptr.h:235
void swap(RefPtr< T_CppObject > &other)
Swap the contents of two RefPtr<>.
Definition: refptr.h:358
RefPtr(T_CppObject *cpp_object, int *refcount, Mutex *refmutex)
For use only in the internal implementation of sharedptr.
Definition: refptr.h:315
RefPtr< T_CppObject > & operator=(T_CppObject *ptr)
Assign object and claim ownership.
Definition: refptr.h:408
static RefPtr< T_CppObject > cast_const(const RefPtr< T_CastFrom > &src)
Cast to non-const.
Definition: refptr.h:205
bool operator==(const RefPtr< T_CppObject > &src) const
Tests whether the RefPtr<> point to the same underlying instance.
Definition: refptr.h:427
Fawkes library namespace.