Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11306 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 9.5 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    nullptr. 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::Destroyable, 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 nullptr (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 nullptr (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 Destroyable (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        orxout() << "Object destroyed" << 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 "core/CorePrereqs.h"
84
85#include <cassert>
86
87#include "core/object/Destroyable.h"
88#include "core/command/Functor.h"
89
90namespace orxonox
91{
92    /**
93        @brief WeakPtr wraps a pointer to an object, which becomes nullptr 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_(nullptr), base_(nullptr), callback_(nullptr)
103            {
104            }
105
106            /// Constructor: Initializes the weak pointer with a pointer to an object.
107            inline WeakPtr(T* pointer) : pointer_(pointer), base_(pointer), callback_(nullptr)
108            {
109                this->registerAsDestructionListener(this->base_);
110            }
111
112            /// Copy-constructor
113            inline WeakPtr(const WeakPtr& other) : pointer_(other.pointer_), base_(other.base_), callback_(nullptr)
114            {
115                this->registerAsDestructionListener(this->base_);
116            }
117
118            /// Copy-constructor for weak pointers to objects of another class.
119            template <class O>
120            inline WeakPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.getBase()), callback_(nullptr)
121            {
122                this->registerAsDestructionListener(this->base_);
123            }
124
125            /// Destructor
126            virtual inline ~WeakPtr()
127            {
128                this->unregisterAsDestructionListener(this->base_);
129            }
130
131            /// Assigns a new pointer.
132            inline WeakPtr& operator=(T* pointer)
133            {
134                WeakPtr(pointer).swap(*this);
135                return *this;
136            }
137
138            /// Assigns the wrapped pointer of another WeakPtr.
139            inline WeakPtr& operator=(WeakPtr other)
140            {
141                other.swap(*this);
142                return *this;
143            }
144
145            /// Assigns the wrapped pointer of a WeakPtr of another class
146            template <class O>
147            inline WeakPtr& operator=(const WeakPtr<O>& other)
148            {
149                WeakPtr(other).swap(*this);
150                return *this;
151            }
152
153            /// Returns the wrapped pointer as @c T*
154            inline T* get() const
155            {
156                return this->pointer_;
157            }
158
159            /// Returns the wrapped pointer as @c Destroyable*
160            inline Destroyable* getBase() const
161            {
162                return this->base_;
163            }
164
165            /// Implicitly converts the WeakPtr to a pointer of type @c T*
166            inline operator T*() const
167            {
168                return this->pointer_;
169            }
170
171            /// Overloaded operator, returns a pointer to the stored object.
172            inline T* operator->() const
173            {
174                assert(this->pointer_ != nullptr);
175                return this->pointer_;
176            }
177
178            /// Overloaded operator, returns a reference to the stored object.
179            inline T& operator*() const
180            {
181                assert(this->pointer_ != nullptr);
182                return *this->pointer_;
183            }
184
185            /// Returns true if the pointer is not nullptr.
186            inline explicit operator bool() const
187            {
188                return (this->pointer_ != nullptr);
189            }
190
191            /// Swaps the contents of two weak pointers.
192            inline void swap(WeakPtr& other)
193            {
194                this->unregisterAsDestructionListener(this->base_);
195                other.unregisterAsDestructionListener(other.base_);
196
197                {
198                    T* temp = this->pointer_;
199                    this->pointer_ = other.pointer_;
200                    other.pointer_ = temp;
201                }
202                {
203                    Destroyable* temp = this->base_;
204                    this->base_ = other.base_;
205                    other.base_ = temp;
206                }
207
208                this->registerAsDestructionListener(this->base_);
209                other.registerAsDestructionListener(other.base_);
210            }
211
212            /// Resets the weak pointer (equivalent to assigning a nullptr).
213            inline void reset()
214            {
215                WeakPtr().swap(*this);
216            }
217
218            /// Registers a callback that will be executed if the stored object is destroyed.
219            inline void setCallback(const FunctorPtr& callback)
220            {
221                this->callback_ = callback;
222            }
223
224            /// Returns the registered callback.
225            inline const FunctorPtr& getCallback() const
226            {
227                return this->callback_;
228            }
229
230        private:
231            /// Will be called by Destroyable::~Destroyable() if the stored object is deleted. Resets the wrapped pointer and executes the callback.
232            virtual inline void objectDeleted() override
233            {
234                this->base_ = nullptr;
235                this->pointer_ = nullptr;
236                if (this->callback_)
237                    (*this->callback_)();
238            }
239
240            T* pointer_;            ///< The wrapped pointer to an object of type @a T
241            Destroyable* base_;    ///< The wrapped pointer, casted up to Destroyable (this is needed because with just a T* pointer, WeakPtr couln't be used with forward declarations)
242            FunctorPtr callback_;   ///< This callback will be executed if the stored object is deleted
243    };
244
245    /// Swaps the contents of two weak pointers.
246    template <class T>
247    void swap(WeakPtr<T>& a, WeakPtr<T>& b)
248    {
249        a.swap(b);
250    }
251
252    /// 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>.
253    template <class T, class U>
254    WeakPtr<T> static_pointer_cast(const WeakPtr<U>& p)
255    {
256        return static_cast<T*>(p.get());
257    }
258
259    /// 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>.
260    template <class T, class U>
261    WeakPtr<T> const_pointer_cast(const WeakPtr<U>& p)
262    {
263        return const_cast<T*>(p.get());
264    }
265
266    /// 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>.
267    template <class T, class U>
268    WeakPtr<T> dynamic_pointer_cast(const WeakPtr<U>& p)
269    {
270        return orxonox_cast<T*>(p.get());
271    }
272}
273
274#endif /* _WeakPtr_H__ */
Note: See TracBrowser for help on using the repository browser.