Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/src/libraries/core/WeakPtr.h @ 7989

Last change on this file since 7989 was 7938, checked in by rgrieder, 14 years ago

Fixed mingw 3 build and removed a warning due to non-virtual destructors.

  • Property svn:eol-style set to native
File size: 9.8 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                this->registerAsDestructionListener(this->base_);
115            }
116
117            /// Copy-constructor
118            inline WeakPtr(const WeakPtr& other) : pointer_(other.pointer_), base_(other.base_), callback_(0)
119            {
120                this->registerAsDestructionListener(this->base_);
121            }
122
123            /// Copy-constructor for weak pointers to objects of another class.
124            template <class O>
125            inline WeakPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.base_), callback_(0)
126            {
127                this->registerAsDestructionListener(this->base_);
128            }
129
130            /// Destructor
131            inline virtual ~WeakPtr()
132            {
133                this->unregisterAsDestructionListener(this->base_);
134            }
135
136            /// Used to assign a null pointer.
137            inline WeakPtr& operator=(int)
138            {
139                WeakPtr(0).swap(*this);
140                return *this;
141            }
142
143            /// Assigns a new pointer.
144            inline WeakPtr& operator=(T* pointer)
145            {
146                WeakPtr(pointer).swap(*this);
147                return *this;
148            }
149
150            /// Assigns the wrapped pointer of another WeakPtr.
151            inline WeakPtr& operator=(const WeakPtr& other)
152            {
153                WeakPtr(other).swap(*this);
154                return *this;
155            }
156
157            /// Assigns the wrapped pointer of a WeakPtr of another class
158            template <class O>
159            inline WeakPtr& operator=(const WeakPtr<O>& other)
160            {
161                WeakPtr(other).swap(*this);
162                return *this;
163            }
164
165            /// Returns the wrapped pointer as @c T*
166            inline T* get() const
167            {
168                return this->pointer_;
169            }
170
171            /// Returns the wrapped pointer as @c OrxonoxClass*
172            inline OrxonoxClass* getBase() const
173            {
174                return this->base_;
175            }
176
177            /// Implicitly converts the WeakPtr to a pointer of type @c T*
178            inline operator T*() const
179            {
180                return this->pointer_;
181            }
182
183            /// Overloaded operator, returns a pointer to the stored object.
184            inline T* operator->() const
185            {
186                assert(this->pointer_ != 0);
187                return this->pointer_;
188            }
189
190            /// Overloaded operator, returns a reference to the stored object.
191            inline T& operator*() const
192            {
193                assert(this->pointer_ != 0);
194                return *this->pointer_;
195            }
196
197            /// Returns true if the wrapped pointer is NULL.
198            inline bool operator!() const
199            {
200                return (this->pointer_ == 0);
201            }
202
203            /// Swaps the contents of two weak pointers.
204            inline void swap(WeakPtr& other)
205            {
206                this->unregisterAsDestructionListener(this->base_);
207                other.unregisterAsDestructionListener(other.base_);
208
209                {
210                    T* temp = this->pointer_;
211                    this->pointer_ = other.pointer_;
212                    other.pointer_ = temp;
213                }
214                {
215                    OrxonoxClass* temp = this->base_;
216                    this->base_ = other.base_;
217                    other.base_ = temp;
218                }
219
220                this->registerAsDestructionListener(this->base_);
221                other.registerAsDestructionListener(other.base_);
222            }
223
224            /// Resets the weak pointer (equivalent to assigning a NULL pointer).
225            inline void reset()
226            {
227                WeakPtr().swap(*this);
228            }
229
230            /// Registers a callback that will be executed if the stored object is destroyed.
231            inline void setCallback(const FunctorPtr& callback)
232            {
233                this->callback_ = callback;
234            }
235
236            /// Returns the registered callback.
237            inline const FunctorPtr& getCallback() const
238            {
239                return this->callback_;
240            }
241
242        private:
243            /// Will be called by OrxonoxClass::~OrxonoxClass() if the stored object is deleted. Resets the wrapped pointer and executes the callback.
244            inline void objectDeleted()
245            {
246                this->base_ = 0;
247                this->pointer_ = 0;
248                if (this->callback_)
249                    (*this->callback_)();
250            }
251
252            T* pointer_;            ///< The wrapped pointer to an object of type @a T
253            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)
254            FunctorPtr callback_;   ///< This callback will be executed if the stored object is deleted
255    };
256
257    /// Swaps the contents of two weak pointers.
258    template <class T>
259    void swap(WeakPtr<T>& a, WeakPtr<T>& b)
260    {
261        a.swap(b);
262    }
263
264    /// 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>.
265    template <class T, class U>
266    WeakPtr<T> static_pointer_cast(const WeakPtr<U>& p)
267    {
268        return static_cast<T*>(p.get());
269    }
270
271    /// 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>.
272    template <class T, class U>
273    WeakPtr<T> const_pointer_cast(const WeakPtr<U>& p)
274    {
275        return const_cast<T*>(p.get());
276    }
277
278    /// 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>.
279    template <class T, class U>
280    WeakPtr<T> dynamic_pointer_cast(const WeakPtr<U>& p)
281    {
282        return orxonox_cast<T*>(p.get());
283    }
284}
285
286#endif /* _WeakPtr_H__ */
Note: See TracBrowser for help on using the repository browser.