Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mergeFS18/src/libraries/core/object/StrongPtr.h @ 12068

Last change on this file since 12068 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: 11.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    @defgroup SmartPtr StrongPtr<T> and WeakPtr<T>
33    @ingroup Object
34*/
35
36/**
37    @file
38    @ingroup Object SmartPtr
39    @brief Definition of StrongPtr<T>, wraps a pointer to an object and keeps it alive.
40
41    @anchor StrongPtrExample
42
43    orxonox::StrongPtr is an implementation of a smart pointer - it wraps a pointer to an
44    object  and keeps this object alive until no StrongPtr points to this object anymore.
45    In contrast to std::shared_ptr, StrongPtr works only with classes that are derived
46    from orxonox::Destroyable, because it's an intrusive implementation, meaning the
47    reference counter is stored in the object itself.
48
49    It's possible to use normal pointers and strong pointers to an object simultaneously.
50    You don't have to use StrongPtr all the time, you can create a StrongPtr for an object
51    at any time and also convert it back to a normal pointer if you like. This is possible
52    because the reference counter is stored in the object itself and not in StrongPtr (in
53    contrast to std::shared_ptr).
54
55    @b Important: If you want to delete an object, you must not use @c delete @c object but
56    rather @c object->destroy(). This function will check if there are strong pointers
57    pointing to the object. If yes, the object will be kept alive until all strong pointers
58    are destroyed. If no, the object is deleted instantly.
59
60    If all strong pointers that point to an object are destroyed, but you never called
61    @c object->destroy() before, the object will not be deleted! All a StrongPtr will do
62    is to really just keep an object alive, but it will not delete it automatically
63    unless you tried to destroy it before.
64
65    Example:
66    @code
67    class MyClass                                           // class declaration
68    {
69        public:
70            void setObject(OtherClass* object)              // passes a normal pointer which will be stored in a StrongPtr
71                { this->object_ = object; }
72
73            OtherClass* getObject() const                   // converts the StrongPtr to a normal pointer and returns it
74                { return this->object_; }
75
76        private:
77            StrongPtr<OtherClass> object_;                  // a pointer to an instance of OtherClass is stored in a StrongPtr
78    };
79    @endcode
80    In this example we assume that OtherClass is a child of Destroyable. We don't care
81    about the inheritance of MyClass though.
82
83    Now we create an instance of MyClass and assign a pointer to an instance of OtherClass:
84    @code
85    MyClass* myclass = new MyClass();                       // create an instance of MyClass
86    OtherClass* object = new OtherClass();                  // create an instance of OtherClass
87    myclass->setObject(object);                             // the object is now stored in a StrongPtr inside myclass
88
89    object->destroy();                                      // we try to destroy object, but there's still a StrongPtr pointing at it.
90
91    # object still exists at this point (because a StrongPtr points at it)
92
93    delete myclass;                                         // now we delete myclass, which also destroys the StrongPtr
94
95    # object doesn't exist anymore (because the StrongPtr is now destroyed)
96    @endcode
97
98    Now we look at the same example, but we first delete myclass, then destroy object:
99    @code
100    MyClass* myclass = new MyClass();                       // create an instance of MyClass
101    OtherClass* object = new OtherClass();                  // create an instance of OtherClass
102    myclass->setObject(object);                             // the object is now stored in a StrongPtr inside myclass
103
104    delete myclass;                                         // we delete myclass, which also destroys the StrongPtr
105
106    # object still exists at this point (because destroy() was not called yet)
107
108    object->destroy();                                      // now we try to destroy object, which works instantly
109
110    # object doesn't exist anymore (because we just destroyed it)
111    @endcode
112
113    Note that in any case @c object->destroy() has to be called to delete the object.
114    However if a StrongPtr points at it, the destruction is delayed until all StrongPtr
115    are destroyed.
116*/
117
118#ifndef _StrongPtr_H__
119#define _StrongPtr_H__
120
121#include "core/CorePrereqs.h"
122
123#include <cassert>
124
125#include "core/object/Destroyable.h"
126#include "WeakPtr.h"
127
128namespace orxonox
129{
130    /**
131        @brief A strong pointer which wraps a pointer to an object and keeps this object alive as long as the strong pointer exists.
132
133        @see See @ref StrongPtrExample "this description" for more information and an example.
134    */
135    template <class T>
136    class StrongPtr
137    {
138        public:
139            /// Constructor: Initializes the strong pointer with a null pointer.
140            inline StrongPtr() : pointer_(nullptr), base_(nullptr)
141            {
142            }
143
144            /// Constructor: Initializes the strong pointer with a pointer to an object. @param pointer The pointer
145            inline StrongPtr(T* pointer) : pointer_(pointer), base_(pointer)
146            {
147                if (this->base_)
148                    this->base_->incrementReferenceCount();
149            }
150
151            /// Copy-constructor
152            inline StrongPtr(const StrongPtr& other) : pointer_(other.pointer_), base_(other.base_)
153            {
154                if (this->base_)
155                    this->base_->incrementReferenceCount();
156            }
157
158            /// Copy-constructor for strong pointers to objects of another class.
159            template <class O>
160            inline StrongPtr(const StrongPtr<O>& other) : pointer_(other.get()), base_(other.getBase())
161            {
162                if (this->base_)
163                    this->base_->incrementReferenceCount();
164            }
165
166            /// Constructor: Initializes the strong pointer with the pointer that is stored in a WeakPtr.
167            template <class O>
168            inline StrongPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.getBase())
169            {
170                if (this->base_)
171                    this->base_->incrementReferenceCount();
172            }
173
174            /// Move-constructor
175            inline StrongPtr(StrongPtr&& other) : pointer_(other.pointer_), base_(other.base_)
176            {
177                other.pointer_ = nullptr;
178                other.base_ = nullptr;
179            }
180
181            /// Destructor: Decrements the reference counter.
182            inline ~StrongPtr()
183            {
184                if (this->base_)
185                    this->base_->decrementReferenceCount();
186            }
187
188            /// Assigns a new pointer.
189            inline StrongPtr& operator=(T* pointer)
190            {
191                StrongPtr(pointer).swap(*this);
192                return *this;
193            }
194
195            /// Assigns the wrapped pointer of another StrongPtr.
196            inline StrongPtr& operator=(StrongPtr other)
197            {
198                other.swap(*this);
199                return *this;
200            }
201
202            /// Assigns the wrapped pointer of a StrongPtr of another class
203            template <class O>
204            inline StrongPtr& operator=(const StrongPtr<O>& other)
205            {
206                StrongPtr(other).swap(*this);
207                return *this;
208            }
209
210            /// Assigns the wrapped pointer of a WeakPtr.
211            template <class O>
212            inline StrongPtr& operator=(const WeakPtr<O>& other)
213            {
214                StrongPtr(other).swap(*this);
215                return *this;
216            }
217
218            /// Returns the wrapped pointer as @c T*
219            inline T* get() const
220            {
221                return this->pointer_;
222            }
223
224            /// Returns the wrapped pointer as @c Destroyable*
225            inline Destroyable* getBase() const
226            {
227                return this->base_;
228            }
229
230            /// Implicitly converts the StrongPtr to a pointer of type @c T*
231            inline operator T*() const
232            {
233                return this->pointer_;
234            }
235
236            /// Overloaded operator, returns a pointer to the stored object.
237            inline T* operator->() const
238            {
239                assert(this->pointer_ != nullptr);
240                return this->pointer_;
241            }
242
243            /// Overloaded operator, returns a reference to the stored object.
244            inline T& operator*() const
245            {
246                assert(this->pointer_ != nullptr);
247                return *this->pointer_;
248            }
249
250            /// Returns true if the pointer is not nullptr.
251            inline explicit operator bool() const
252            {
253                return (this->pointer_ != nullptr);
254            }
255
256            /// Swaps the contents of two strong pointers.
257            inline void swap(StrongPtr& other)
258            {
259                {
260                    T* temp = this->pointer_;
261                    this->pointer_ = other.pointer_;
262                    other.pointer_ = temp;
263                }
264                {
265                    Destroyable* temp = this->base_;
266                    this->base_ = other.base_;
267                    other.base_ = temp;
268                }
269            }
270
271            /// Resets the strong pointer (equivalent to assigning a nullptr).
272            inline void reset()
273            {
274                StrongPtr().swap(*this);
275            }
276
277        private:
278            T* pointer_;            ///< The wrapped pointer to an object of type @a T
279            Destroyable* base_;    ///< The wrapped pointer, casted up to Destroyable (this is needed because with just a T* pointer, StrongPtr couln't be used with forward declarations)
280    };
281
282    /// Swaps the contents of two strong pointers.
283    template <class T>
284    void swap(StrongPtr<T>& a, StrongPtr<T>& b)
285    {
286        a.swap(b);
287    }
288
289    /// Uses a static_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new StrongPtr<T>.
290    template <class T, class U>
291    StrongPtr<T> static_pointer_cast(const StrongPtr<U>& p)
292    {
293        return static_cast<T*>(p.get());
294    }
295
296    /// Uses a const_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new StrongPtr<T>.
297    template <class T, class U>
298    StrongPtr<T> const_pointer_cast(const StrongPtr<U>& p)
299    {
300        return const_cast<T*>(p.get());
301    }
302
303    /// Uses a dynamic_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new StrongPtr<T>.
304    template <class T, class U>
305    StrongPtr<T> dynamic_pointer_cast(const StrongPtr<U>& p)
306    {
307        return orxonox_cast<T*>(p.get());
308    }
309}
310
311#endif /* _StrongPtr_H__ */
Note: See TracBrowser for help on using the repository browser.