Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/libraries/core/object/StrongPtr.h @ 10555

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

renamed SmartPtr to StrongPtr (now we have weak and strong pointers)

  • Property svn:eol-style set to native
File size: 11.5 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
[10555]144            /// Constructor: Initializes the strong pointer with a pointer to an object. @param pointer The pointer @param bAddRef If true, the reference counter is increased. Don't set this to false unless you know exactly what you're doing! (for example to avoid circular references if the @c this pointer of the possessing object is stored)
145            inline StrongPtr(T* pointer, bool bAddRef = true) : pointer_(pointer), base_(pointer)
[5804]146            {
[5805]147                if (this->base_ && bAddRef)
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>
[10555]160            inline StrongPtr(const StrongPtr<O>& other) : pointer_(other.get()), base_(other.base_)
[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
[7401]174            /// Destructor: Decrements the reference counter.
[10555]175            inline ~StrongPtr()
[5804]176            {
[5805]177                if (this->base_)
178                    this->base_->decrementReferenceCount();
[5804]179            }
[6417]180
[7401]181            /// Assigns a new pointer.
[10555]182            inline StrongPtr& operator=(T* pointer)
[5804]183            {
[10555]184                StrongPtr(pointer).swap(*this);
[5804]185                return *this;
186            }
187
[10555]188            /// Assigns the wrapped pointer of another StrongPtr.
189            inline StrongPtr& operator=(const StrongPtr& other)
[5804]190            {
[10555]191                StrongPtr(other).swap(*this);
[5804]192                return *this;
193            }
194
[10555]195            /// Assigns the wrapped pointer of a StrongPtr of another class
[5804]196            template <class O>
[10555]197            inline StrongPtr& operator=(const StrongPtr<O>& other)
[5804]198            {
[10555]199                StrongPtr(other).swap(*this);
[5804]200                return *this;
201            }
202
[7401]203            /// Assigns the wrapped pointer of a WeakPtr.
[5823]204            template <class O>
[10555]205            inline StrongPtr& operator=(const WeakPtr<O>& other)
[5823]206            {
[10555]207                StrongPtr(other).swap(*this);
[5823]208                return *this;
209            }
210
[7401]211            /// Returns the wrapped pointer as @c T*
[5804]212            inline T* get() const
213            {
214                return this->pointer_;
215            }
216
[9571]217            /// Returns the wrapped pointer as @c Destroyable*
218            inline Destroyable* getBase() const
[5823]219            {
220                return this->base_;
221            }
222
[10555]223            /// Implicitly converts the StrongPtr to a pointer of type @c T*
[5804]224            inline operator T*() const
[5805]225            {
[5804]226                return this->pointer_;
227            }
228
[7401]229            /// Overloaded operator, returns a pointer to the stored object.
[5804]230            inline T* operator->() const
231            {
[5807]232                assert(this->pointer_ != 0);
[5804]233                return this->pointer_;
234            }
235
[7401]236            /// Overloaded operator, returns a reference 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            /// Returns true if the wrapped pointer is NULL.
[5804]244            inline bool operator!() const
245            {
246                return (this->pointer_ == 0);
247            }
248
[10555]249            /// Swaps the contents of two strong pointers.
250            inline void swap(StrongPtr& other)
[5804]251            {
[5805]252                {
253                    T* temp = this->pointer_;
254                    this->pointer_ = other.pointer_;
255                    other.pointer_ = temp;
256                }
257                {
[9571]258                    Destroyable* temp = this->base_;
[5805]259                    this->base_ = other.base_;
260                    other.base_ = temp;
261                }
[5804]262            }
263
[10555]264            /// Resets the strong pointer (equivalent to assigning a NULL pointer).
[5804]265            inline void reset()
266            {
[10555]267                StrongPtr().swap(*this);
[5804]268            }
269
270        private:
[7401]271            T* pointer_;            ///< The wrapped pointer to an object of type @a T
[10555]272            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]273    };
274
[10555]275    /// Swaps the contents of two strong pointers.
[5804]276    template <class T>
[10555]277    void swap(StrongPtr<T>& a, StrongPtr<T>& b)
[5804]278    {
279        a.swap(b);
280    }
281
[10555]282    /// 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]283    template <class T, class U>
[10555]284    StrongPtr<T> static_pointer_cast(const StrongPtr<U>& p)
[5804]285    {
286        return static_cast<T*>(p.get());
287    }
288
[10555]289    /// 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]290    template <class T, class U>
[10555]291    StrongPtr<T> const_pointer_cast(const StrongPtr<U>& p)
[5804]292    {
293        return const_cast<T*>(p.get());
294    }
295
[10555]296    /// 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]297    template <class T, class U>
[10555]298    StrongPtr<T> dynamic_pointer_cast(const StrongPtr<U>& p)
[5804]299    {
[7268]300        return orxonox_cast<T*>(p.get());
[5804]301    }
302}
303
[10555]304#endif /* _StrongPtr_H__ */
Note: See TracBrowser for help on using the repository browser.