Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/libraries/core/object/StrongPtr.h @ 10745

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

added move-constructor for StrongPtr and SharedPtr. for WeakPtr this is not useful because the weakPtr is registered in Destroyable, so a copy-constructor must be used anyway

  • Property svn:eol-style set to native
File size: 11.4 KB
RevLine 
[5804]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/**
[10555]32    @defgroup SmartPtr StrongPtr<T> and WeakPtr<T>
[7401]33    @ingroup Object
34*/
35
36/**
37    @file
38    @ingroup Object SmartPtr
[10555]39    @brief Definition of StrongPtr<T>, wraps a pointer to an object and keeps it alive.
[7401]40
[10555]41    @anchor StrongPtrExample
[7401]42
[10555]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 orxonox::SharedPtr, StrongPtr works only with classes that are derived
[9571]46    from orxonox::Destroyable, because it's an intrusive implementation, meaning the
[7401]47    reference counter is stored in the object itself.
48
[10555]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
[7401]51    at any time and also convert it back to a normal pointer if you like. This is possible
[10555]52    because the reference counter is stored in the object itself and not in StrongPtr (in
[7401]53    contrast to SharedPtr).
54
55    @b Important: If you want to delete an object, you must not use @c delete @c object but
[10555]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
[7401]58    are destroyed. If no, the object is deleted instantly.
59
[10555]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
[7401]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:
[10555]70            void setObject(OtherClass* object)              // passes a normal pointer which will be stored in a StrongPtr
[7401]71                { this->object_ = object; }
72
[10555]73            OtherClass* getObject() const                   // converts the StrongPtr to a normal pointer and returns it
[7401]74                { return this->object_; }
75
76        private:
[10555]77            StrongPtr<OtherClass> object_;                  // a pointer to an instance of OtherClass is stored in a StrongPtr
[7401]78    };
79    @endcode
[9571]80    In this example we assume that OtherClass is a child of Destroyable. We don't care
[7401]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
[10555]87    myclass->setObject(object);                             // the object is now stored in a StrongPtr inside myclass
[7401]88
[10555]89    object->destroy();                                      // we try to destroy object, but there's still a StrongPtr pointing at it.
[7401]90
[10555]91    # object still exists at this point (because a StrongPtr points at it)
[7401]92
[10555]93    delete myclass;                                         // now we delete myclass, which also destroys the StrongPtr
[7401]94
[10555]95    # object doesn't exist anymore (because the StrongPtr is now destroyed)
[7401]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
[10555]102    myclass->setObject(object);                             // the object is now stored in a StrongPtr inside myclass
[7401]103
[10555]104    delete myclass;                                         // we delete myclass, which also destroys the StrongPtr
[7401]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.
[10555]114    However if a StrongPtr points at it, the destruction is delayed until all StrongPtr
[7401]115    are destroyed.
116*/
117
[10555]118#ifndef _StrongPtr_H__
119#define _StrongPtr_H__
[5804]120
[9557]121#include "core/CorePrereqs.h"
[5804]122
[5807]123#include <cassert>
[5823]124
[9571]125#include "core/object/Destroyable.h"
[5823]126#include "WeakPtr.h"
[5804]127
128namespace orxonox
129{
[7401]130    /**
[10555]131        @brief A strong pointer which wraps a pointer to an object and keeps this object alive as long as the strong pointer exists.
[7401]132
[10555]133        @see See @ref StrongPtrExample "this description" for more information and an example.
[7401]134    */
[5804]135    template <class T>
[10555]136    class StrongPtr
[5804]137    {
138        public:
[10555]139            /// Constructor: Initializes the strong pointer with a null pointer.
140            inline StrongPtr() : pointer_(0), base_(0)
[5804]141            {
142            }
143
[10578]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)
[5804]146            {
[10578]147                if (this->base_)
[5805]148                    this->base_->incrementReferenceCount();
[5804]149            }
150
[7401]151            /// Copy-constructor
[10555]152            inline StrongPtr(const StrongPtr& other) : pointer_(other.pointer_), base_(other.base_)
[5805]153            {
154                if (this->base_)
155                    this->base_->incrementReferenceCount();
156            }
157
[10555]158            /// Copy-constructor for strong pointers to objects of another class.
[5804]159            template <class O>
[10744]160            inline StrongPtr(const StrongPtr<O>& other) : pointer_(other.get()), base_(other.getBase())
[5804]161            {
[5805]162                if (this->base_)
163                    this->base_->incrementReferenceCount();
[5804]164            }
165
[10555]166            /// Constructor: Initializes the strong pointer with the pointer that is stored in a WeakPtr.
[5823]167            template <class O>
[10555]168            inline StrongPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.getBase())
[5823]169            {
170                if (this->base_)
171                    this->base_->incrementReferenceCount();
172            }
173
[10745]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
[7401]181            /// Destructor: Decrements the reference counter.
[10555]182            inline ~StrongPtr()
[5804]183            {
[5805]184                if (this->base_)
185                    this->base_->decrementReferenceCount();
[5804]186            }
[6417]187
[7401]188            /// Assigns a new pointer.
[10555]189            inline StrongPtr& operator=(T* pointer)
[5804]190            {
[10555]191                StrongPtr(pointer).swap(*this);
[5804]192                return *this;
193            }
194
[10555]195            /// Assigns the wrapped pointer of another StrongPtr.
[10745]196            inline StrongPtr& operator=(StrongPtr other)
[5804]197            {
[10745]198                other.swap(*this);
[5804]199                return *this;
200            }
201
[10555]202            /// Assigns the wrapped pointer of a StrongPtr of another class
[5804]203            template <class O>
[10555]204            inline StrongPtr& operator=(const StrongPtr<O>& other)
[5804]205            {
[10555]206                StrongPtr(other).swap(*this);
[5804]207                return *this;
208            }
209
[7401]210            /// Assigns the wrapped pointer of a WeakPtr.
[5823]211            template <class O>
[10555]212            inline StrongPtr& operator=(const WeakPtr<O>& other)
[5823]213            {
[10555]214                StrongPtr(other).swap(*this);
[5823]215                return *this;
216            }
217
[7401]218            /// Returns the wrapped pointer as @c T*
[5804]219            inline T* get() const
220            {
221                return this->pointer_;
222            }
223
[9571]224            /// Returns the wrapped pointer as @c Destroyable*
225            inline Destroyable* getBase() const
[5823]226            {
227                return this->base_;
228            }
229
[10555]230            /// Implicitly converts the StrongPtr to a pointer of type @c T*
[5804]231            inline operator T*() const
[5805]232            {
[5804]233                return this->pointer_;
234            }
235
[7401]236            /// Overloaded operator, returns a pointer to the stored object.
[5804]237            inline T* operator->() const
238            {
[5807]239                assert(this->pointer_ != 0);
[5804]240                return this->pointer_;
241            }
242
[7401]243            /// Overloaded operator, returns a reference to the stored object.
[5804]244            inline T& operator*() const
245            {
[5807]246                assert(this->pointer_ != 0);
[5804]247                return *this->pointer_;
248            }
249
[7401]250            /// Returns true if the wrapped pointer is NULL.
[5804]251            inline bool operator!() const
252            {
253                return (this->pointer_ == 0);
254            }
255
[10555]256            /// Swaps the contents of two strong pointers.
257            inline void swap(StrongPtr& other)
[5804]258            {
[5805]259                {
260                    T* temp = this->pointer_;
261                    this->pointer_ = other.pointer_;
262                    other.pointer_ = temp;
263                }
264                {
[9571]265                    Destroyable* temp = this->base_;
[5805]266                    this->base_ = other.base_;
267                    other.base_ = temp;
268                }
[5804]269            }
270
[10555]271            /// Resets the strong pointer (equivalent to assigning a NULL pointer).
[5804]272            inline void reset()
273            {
[10555]274                StrongPtr().swap(*this);
[5804]275            }
276
277        private:
[7401]278            T* pointer_;            ///< The wrapped pointer to an object of type @a T
[10555]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)
[5804]280    };
281
[10555]282    /// Swaps the contents of two strong pointers.
[5804]283    template <class T>
[10555]284    void swap(StrongPtr<T>& a, StrongPtr<T>& b)
[5804]285    {
286        a.swap(b);
287    }
288
[10555]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>.
[5804]290    template <class T, class U>
[10555]291    StrongPtr<T> static_pointer_cast(const StrongPtr<U>& p)
[5804]292    {
293        return static_cast<T*>(p.get());
294    }
295
[10555]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>.
[5804]297    template <class T, class U>
[10555]298    StrongPtr<T> const_pointer_cast(const StrongPtr<U>& p)
[5804]299    {
300        return const_cast<T*>(p.get());
301    }
302
[10555]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>.
[5804]304    template <class T, class U>
[10555]305    StrongPtr<T> dynamic_pointer_cast(const StrongPtr<U>& p)
[5804]306    {
[7268]307        return orxonox_cast<T*>(p.get());
[5804]308    }
309}
310
[10555]311#endif /* _StrongPtr_H__ */
Note: See TracBrowser for help on using the repository browser.