Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7995 was 7850, checked in by landauf, 14 years ago

moved if(object) condition from WeakPtr to DestructionListener

  • Property svn:eol-style set to native
File size: 9.8 KB
RevLine 
[5823]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
[7401]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
[5823]80#ifndef _WeakPtr_H__
81#define _WeakPtr_H__
82
83#include "CorePrereqs.h"
84
85#include <cassert>
[7268]86#include "Identifier.h"
[5823]87#include "OrxonoxClass.h"
[7284]88#include "command/Functor.h"
[5823]89
90namespace orxonox
91{
[7401]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    */
[5823]97    template <class T>
[7849]98    class WeakPtr : public DestructionListener
[5823]99    {
100        public:
[7401]101            /// Constructor: Initializes the weak pointer with a null pointer.
[5824]102            inline WeakPtr() : pointer_(0), base_(0), callback_(0)
[5823]103            {
104            }
105
[7401]106            /// Constructor: Used to explicitly initialize the weak pointer with a null pointer
[5824]107            inline WeakPtr(int) : pointer_(0), base_(0), callback_(0)
[5823]108            {
109            }
110
[7401]111            /// Constructor: Initializes the weak pointer with a pointer to an object.
[5824]112            inline WeakPtr(T* pointer) : pointer_(pointer), base_(pointer), callback_(0)
[5823]113            {
[7850]114                this->registerAsDestructionListener(this->base_);
[5823]115            }
116
[7401]117            /// Copy-constructor
[5824]118            inline WeakPtr(const WeakPtr& other) : pointer_(other.pointer_), base_(other.base_), callback_(0)
[5823]119            {
[7850]120                this->registerAsDestructionListener(this->base_);
[5823]121            }
122
[7401]123            /// Copy-constructor for weak pointers to objects of another class.
[5823]124            template <class O>
[5824]125            inline WeakPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.base_), callback_(0)
[5823]126            {
[7850]127                this->registerAsDestructionListener(this->base_);
[5823]128            }
129
[7401]130            /// Destructor
[5823]131            inline ~WeakPtr()
132            {
[7850]133                this->unregisterAsDestructionListener(this->base_);
[5823]134            }
[6417]135
[7401]136            /// Used to assign a null pointer.
[7268]137            inline WeakPtr& operator=(int)
[5823]138            {
139                WeakPtr(0).swap(*this);
140                return *this;
141            }
142
[7401]143            /// Assigns a new pointer.
[7268]144            inline WeakPtr& operator=(T* pointer)
[5823]145            {
146                WeakPtr(pointer).swap(*this);
147                return *this;
148            }
149
[7401]150            /// Assigns the wrapped pointer of another WeakPtr.
[7268]151            inline WeakPtr& operator=(const WeakPtr& other)
[5823]152            {
153                WeakPtr(other).swap(*this);
154                return *this;
155            }
156
[7401]157            /// Assigns the wrapped pointer of a WeakPtr of another class
[5823]158            template <class O>
[7268]159            inline WeakPtr& operator=(const WeakPtr<O>& other)
[5823]160            {
161                WeakPtr(other).swap(*this);
162                return *this;
163            }
164
[7401]165            /// Returns the wrapped pointer as @c T*
[5823]166            inline T* get() const
167            {
168                return this->pointer_;
169            }
170
[7401]171            /// Returns the wrapped pointer as @c OrxonoxClass*
[5823]172            inline OrxonoxClass* getBase() const
173            {
174                return this->base_;
175            }
176
[7401]177            /// Implicitly converts the WeakPtr to a pointer of type @c T*
[5823]178            inline operator T*() const
179            {
180                return this->pointer_;
181            }
182
[7401]183            /// Overloaded operator, returns a pointer to the stored object.
[5823]184            inline T* operator->() const
185            {
186                assert(this->pointer_ != 0);
187                return this->pointer_;
188            }
189
[7401]190            /// Overloaded operator, returns a reference to the stored object.
[5823]191            inline T& operator*() const
192            {
193                assert(this->pointer_ != 0);
194                return *this->pointer_;
195            }
196
[7401]197            /// Returns true if the wrapped pointer is NULL.
[5823]198            inline bool operator!() const
199            {
200                return (this->pointer_ == 0);
201            }
202
[7401]203            /// Swaps the contents of two weak pointers.
[5823]204            inline void swap(WeakPtr& other)
205            {
[7850]206                this->unregisterAsDestructionListener(this->base_);
207                other.unregisterAsDestructionListener(other.base_);
[6417]208
[5823]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                }
[5825]219
[7850]220                this->registerAsDestructionListener(this->base_);
221                other.registerAsDestructionListener(other.base_);
[5823]222            }
223
[7401]224            /// Resets the weak pointer (equivalent to assigning a NULL pointer).
[5823]225            inline void reset()
226            {
227                WeakPtr().swap(*this);
228            }
[6417]229
[7401]230            /// Registers a callback that will be executed if the stored object is destroyed.
[7284]231            inline void setCallback(const FunctorPtr& callback)
[5824]232            {
233                this->callback_ = callback;
234            }
[6417]235
[7401]236            /// Returns the registered callback.
[7284]237            inline const FunctorPtr& getCallback() const
[5824]238            {
239                return this->callback_;
240            }
[5823]241
242        private:
[7401]243            /// Will be called by OrxonoxClass::~OrxonoxClass() if the stored object is deleted. Resets the wrapped pointer and executes the callback.
[5824]244            inline void objectDeleted()
245            {
[5825]246                this->base_ = 0;
247                this->pointer_ = 0;
[5824]248                if (this->callback_)
249                    (*this->callback_)();
250            }
[6417]251
[7401]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
[5823]255    };
256
[7401]257    /// Swaps the contents of two weak pointers.
[5823]258    template <class T>
259    void swap(WeakPtr<T>& a, WeakPtr<T>& b)
260    {
261        a.swap(b);
262    }
263
[7401]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>.
[5823]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
[7401]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>.
[5823]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
[7401]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>.
[5823]279    template <class T, class U>
280    WeakPtr<T> dynamic_pointer_cast(const WeakPtr<U>& p)
281    {
[7268]282        return orxonox_cast<T*>(p.get());
[5823]283    }
284}
285
286#endif /* _WeakPtr_H__ */
Note: See TracBrowser for help on using the repository browser.