Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel/src/libraries/core/WeakPtr.h @ 8498

Last change on this file since 8498 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

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