Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/WeakPtr.h @ 7849

Last change on this file since 7849 was 7849, checked in by landauf, 13 years ago

Added DestructionListener, a class which gets notified if a certain object (of type OrxonoxClass) is destroyed. So far only WeakPtr was able to do this, now every class that inherits from DestructionListener can do so.

  • Property svn:eol-style set to native
File size: 10.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29// Inspired by boost::intrusive_ptr by Peter Dimov
30
31/**
32    @file
33    @ingroup Object SmartPtr
34    @brief Definition of WeakPtr<T>, wraps a pointer to an object.
35
36    @anchor WeakPtrExample
37
38    A WeakPtr wraps a pointer to an object. If the object gets deleted, the WeakPtr becomes
39    NULL. This can be used to store pointers to objects without knowing when they will be
40    destroyed.
41
42    WeakPtr works only with objects that are derived from orxonox::OrxonoxClass, because
43    WeakPtr is intrusive and registers itself in the stored object, to get a notification if
44    the object is being deleted.
45
46    Example:
47    @code
48    MyClass* object = new MyClass();                    // create an instance of MyClass
49
50    WeakPtr<MyClass> pointer = object;                  // create a WeakPtr and assign the object
51
52    if (pointer)                                        // checks if pointer is not NULL (which is true)
53        pointer->someFunction();                        // calls MyClass::someFunction()
54
55    object->destroy();                                  // calls destroy() which deletes the object
56
57    if (pointer)                                        // checks if pointer is not NULL (which is now false)
58        pointer->someFunction();                        // this will not be executed
59    @endcode
60    In this example we assumed that MyClass is derived of OrxonoxClass (otherwise it couldn't
61    be used with a WeakPtr).
62
63    A callback can be registerd with the WeakPtr that will be called if the object gets deleted.
64    @code
65    void myCallback()                                   // definition of the callback function
66    {
67        COUT(0) << "Object destroyed" << std::endl;
68    }
69
70    MyClass* object = new MyClass();                    // create an instance of MyClass
71
72    WeakPtr<MyClass> pointer = object;                  // create a WeakPtr and assign the object
73
74    pointer.setCallback(createFunctor(&myCallback));    // defines a callback
75
76    object->destroy();                                  // calls destroy() which deletes the object. prints "Object destroyed" to the console
77    @endcode
78*/
79
80#ifndef _WeakPtr_H__
81#define _WeakPtr_H__
82
83#include "CorePrereqs.h"
84
85#include <cassert>
86#include "Identifier.h"
87#include "OrxonoxClass.h"
88#include "command/Functor.h"
89
90namespace orxonox
91{
92    /**
93        @brief WeakPtr wraps a pointer to an object, which becomes NULL if the object is deleted.
94
95        @see See @ref WeakPtrExample "this description" for more information and an example.
96    */
97    template <class T>
98    class WeakPtr : public DestructionListener
99    {
100        public:
101            /// Constructor: Initializes the weak pointer with a null pointer.
102            inline WeakPtr() : pointer_(0), base_(0), callback_(0)
103            {
104            }
105
106            /// Constructor: Used to explicitly initialize the weak pointer with a null pointer
107            inline WeakPtr(int) : pointer_(0), base_(0), callback_(0)
108            {
109            }
110
111            /// Constructor: Initializes the weak pointer with a pointer to an object.
112            inline WeakPtr(T* pointer) : pointer_(pointer), base_(pointer), callback_(0)
113            {
114                if (this->base_)
115                    this->registerAsDestructionListener(this->base_);
116            }
117
118            /// Copy-constructor
119            inline WeakPtr(const WeakPtr& other) : pointer_(other.pointer_), base_(other.base_), callback_(0)
120            {
121                if (this->base_)
122                    this->registerAsDestructionListener(this->base_);
123            }
124
125            /// Copy-constructor for weak pointers to objects of another class.
126            template <class O>
127            inline WeakPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.base_), callback_(0)
128            {
129                if (this->base_)
130                    this->registerAsDestructionListener(this->base_);
131            }
132
133            /// Destructor
134            inline ~WeakPtr()
135            {
136                if (this->base_)
137                    this->unregisterAsDestructionListener(this->base_);
138
139            }
140
141            /// Used to assign a null pointer.
142            inline WeakPtr& operator=(int)
143            {
144                WeakPtr(0).swap(*this);
145                return *this;
146            }
147
148            /// Assigns a new pointer.
149            inline WeakPtr& operator=(T* pointer)
150            {
151                WeakPtr(pointer).swap(*this);
152                return *this;
153            }
154
155            /// Assigns the wrapped pointer of another WeakPtr.
156            inline WeakPtr& operator=(const WeakPtr& other)
157            {
158                WeakPtr(other).swap(*this);
159                return *this;
160            }
161
162            /// Assigns the wrapped pointer of a WeakPtr of another class
163            template <class O>
164            inline WeakPtr& operator=(const WeakPtr<O>& other)
165            {
166                WeakPtr(other).swap(*this);
167                return *this;
168            }
169
170            /// Returns the wrapped pointer as @c T*
171            inline T* get() const
172            {
173                return this->pointer_;
174            }
175
176            /// Returns the wrapped pointer as @c OrxonoxClass*
177            inline OrxonoxClass* getBase() const
178            {
179                return this->base_;
180            }
181
182            /// Implicitly converts the WeakPtr to a pointer of type @c T*
183            inline operator T*() const
184            {
185                return this->pointer_;
186            }
187
188            /// Overloaded operator, returns a pointer to the stored object.
189            inline T* operator->() const
190            {
191                assert(this->pointer_ != 0);
192                return this->pointer_;
193            }
194
195            /// Overloaded operator, returns a reference to the stored object.
196            inline T& operator*() const
197            {
198                assert(this->pointer_ != 0);
199                return *this->pointer_;
200            }
201
202            /// Returns true if the wrapped pointer is NULL.
203            inline bool operator!() const
204            {
205                return (this->pointer_ == 0);
206            }
207
208            /// Swaps the contents of two weak pointers.
209            inline void swap(WeakPtr& other)
210            {
211                if (this->base_)
212                    this->unregisterAsDestructionListener(this->base_);
213                if (other.base_)
214                    other.unregisterAsDestructionListener(other.base_);
215
216                {
217                    T* temp = this->pointer_;
218                    this->pointer_ = other.pointer_;
219                    other.pointer_ = temp;
220                }
221                {
222                    OrxonoxClass* temp = this->base_;
223                    this->base_ = other.base_;
224                    other.base_ = temp;
225                }
226
227                if (this->base_)
228                    this->registerAsDestructionListener(this->base_);
229                if (other.base_)
230                    other.registerAsDestructionListener(other.base_);
231            }
232
233            /// Resets the weak pointer (equivalent to assigning a NULL pointer).
234            inline void reset()
235            {
236                WeakPtr().swap(*this);
237            }
238
239            /// Registers a callback that will be executed if the stored object is destroyed.
240            inline void setCallback(const FunctorPtr& callback)
241            {
242                this->callback_ = callback;
243            }
244
245            /// Returns the registered callback.
246            inline const FunctorPtr& getCallback() const
247            {
248                return this->callback_;
249            }
250
251        private:
252            /// Will be called by OrxonoxClass::~OrxonoxClass() if the stored object is deleted. Resets the wrapped pointer and executes the callback.
253            inline void objectDeleted()
254            {
255                this->base_ = 0;
256                this->pointer_ = 0;
257                if (this->callback_)
258                    (*this->callback_)();
259            }
260
261            T* pointer_;            ///< The wrapped pointer to an object of type @a T
262            OrxonoxClass* base_;    ///< The wrapped pointer, casted up to OrxonoxClass (this is needed because with just a T* pointer, WeakPtr couln't be used with forward declarations)
263            FunctorPtr callback_;   ///< This callback will be executed if the stored object is deleted
264    };
265
266    /// Swaps the contents of two weak pointers.
267    template <class T>
268    void swap(WeakPtr<T>& a, WeakPtr<T>& b)
269    {
270        a.swap(b);
271    }
272
273    /// Uses a static_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new WeakPtr<T>.
274    template <class T, class U>
275    WeakPtr<T> static_pointer_cast(const WeakPtr<U>& p)
276    {
277        return static_cast<T*>(p.get());
278    }
279
280    /// Uses a const_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new WeakPtr<T>.
281    template <class T, class U>
282    WeakPtr<T> const_pointer_cast(const WeakPtr<U>& p)
283    {
284        return const_cast<T*>(p.get());
285    }
286
287    /// Uses a dynamic_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new WeakPtr<T>.
288    template <class T, class U>
289    WeakPtr<T> dynamic_pointer_cast(const WeakPtr<U>& p)
290    {
291        return orxonox_cast<T*>(p.get());
292    }
293}
294
295#endif /* _WeakPtr_H__ */
Note: See TracBrowser for help on using the repository browser.