yat/utility/SmartPtr.h

Code
Comments
Other
Rev Date Author Line
1044 06 Feb 08 peter 1 #ifndef _theplu_yat_utility_smart_ptr_
1044 06 Feb 08 peter 2 #define _theplu_yat_utility_smart_ptr_
1044 06 Feb 08 peter 3
1044 06 Feb 08 peter 4 // $Id$
1044 06 Feb 08 peter 5
1044 06 Feb 08 peter 6 /*
2119 12 Dec 09 peter 7   Copyright (C) 2008 Jari Häkkinen, Peter Johansson
3992 17 Sep 20 peter 8   Copyright (C) 2012, 2014, 2020 Peter Johansson
1044 06 Feb 08 peter 9
1437 25 Aug 08 peter 10   This file is part of the yat library, http://dev.thep.lu.se/yat
1044 06 Feb 08 peter 11
1044 06 Feb 08 peter 12   The yat library is free software; you can redistribute it and/or
1044 06 Feb 08 peter 13   modify it under the terms of the GNU General Public License as
1486 09 Sep 08 jari 14   published by the Free Software Foundation; either version 3 of the
1044 06 Feb 08 peter 15   License, or (at your option) any later version.
1044 06 Feb 08 peter 16
1044 06 Feb 08 peter 17   The yat library is distributed in the hope that it will be useful,
1044 06 Feb 08 peter 18   but WITHOUT ANY WARRANTY; without even the implied warranty of
1044 06 Feb 08 peter 19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1044 06 Feb 08 peter 20   General Public License for more details.
1044 06 Feb 08 peter 21
1044 06 Feb 08 peter 22   You should have received a copy of the GNU General Public License
1487 10 Sep 08 jari 23   along with yat. If not, see <http://www.gnu.org/licenses/>.
1044 06 Feb 08 peter 24 */
1044 06 Feb 08 peter 25
1044 06 Feb 08 peter 26 #include "yat_assert.h"
1044 06 Feb 08 peter 27
1044 06 Feb 08 peter 28 namespace theplu {
1044 06 Feb 08 peter 29 namespace yat {
1044 06 Feb 08 peter 30 namespace utility {
1044 06 Feb 08 peter 31
1044 06 Feb 08 peter 32   /**
1125 22 Feb 08 peter 33      SmartPtr is a wrapper around a pointer. Default SmartPtr is set
1125 22 Feb 08 peter 34      to be owner of pointer, which implies pointer will be deleted in
1125 22 Feb 08 peter 35      destructor. Pointer can be shared between many SmartPtr, in which
1125 22 Feb 08 peter 36      case a counter is kept updated in copying and assignment telling
1125 22 Feb 08 peter 37      how many owners there are. When the counter reaches zero, the
1125 22 Feb 08 peter 38      pointer is deleted.
2778 19 Jul 12 peter 39
2778 19 Jul 12 peter 40      \internal This is an internal class kept for backward
3992 17 Sep 20 peter 41      compabitility. Users are adviced to use <a
3992 17 Sep 20 peter 42      href="http://www.cplusplus.com/reference/memory/shared_ptr/?kw=shared_ptr">
3992 17 Sep 20 peter 43      std::shared_ptr</a>.
3249 04 Jun 14 peter 44
3249 04 Jun 14 peter 45      \see Deleter
1044 06 Feb 08 peter 46   */
1044 06 Feb 08 peter 47   template<typename T>
2778 19 Jul 12 peter 48   class SmartPtr
1044 06 Feb 08 peter 49   {
1044 06 Feb 08 peter 50   public:
1044 06 Feb 08 peter 51     /**
1044 06 Feb 08 peter 52        \brief Constructor
1050 07 Feb 08 peter 53
1050 07 Feb 08 peter 54        \param p underlying pointer
1050 07 Feb 08 peter 55        \param owner if true SmartPtr will be owner of pointer and if
1050 07 Feb 08 peter 56        there is no more owner delete it in destructor.
1050 07 Feb 08 peter 57
1050 07 Feb 08 peter 58        Never use this constructor to create two SmartPtr to the same
1050 07 Feb 08 peter 59        pointer such as
1050 07 Feb 08 peter 60        \code
1050 07 Feb 08 peter 61        MyClass* my_pointer = new MyClass;
1050 07 Feb 08 peter 62        SmartPtr<MyClass> sp(my_pointer);
1050 07 Feb 08 peter 63        SmartPtr<MyClass> sp2(my_pointer); // this is evil
1050 07 Feb 08 peter 64        \endcode
1050 07 Feb 08 peter 65        since this will cause multiple deletion. Instead use copy constructor
1050 07 Feb 08 peter 66        \code
1050 07 Feb 08 peter 67        MyClass* my_pointer = new MyClass;
1050 07 Feb 08 peter 68        SmartPtr<MyClass> sp(my_pointer);
1050 07 Feb 08 peter 69        SmartPtr<MyClass> sp2(sp);
1050 07 Feb 08 peter 70        \endcode
1050 07 Feb 08 peter 71        so the internal reference counter is updated.
1044 06 Feb 08 peter 72     */
1044 06 Feb 08 peter 73     explicit SmartPtr(T* p=NULL, bool owner=true)
2778 19 Jul 12 peter 74       : pointee_(p)
1044 06 Feb 08 peter 75     {
1044 06 Feb 08 peter 76       if (owner)
1271 09 Apr 08 peter 77         ref_count_ = new unsigned int(1);
1133 23 Feb 08 peter 78       else
1133 23 Feb 08 peter 79         ref_count_ = NULL;
1044 06 Feb 08 peter 80     }
1044 06 Feb 08 peter 81
1044 06 Feb 08 peter 82     /**
1044 06 Feb 08 peter 83        \brief Copy constructor
1044 06 Feb 08 peter 84      */
1044 06 Feb 08 peter 85     SmartPtr(const SmartPtr& other)
1044 06 Feb 08 peter 86       : pointee_(other.pointee_), ref_count_(other.ref_count_)
1044 06 Feb 08 peter 87     {
1044 06 Feb 08 peter 88       if (ref_count_)
1044 06 Feb 08 peter 89         ++(*ref_count_);
1044 06 Feb 08 peter 90     }
2778 19 Jul 12 peter 91
1044 06 Feb 08 peter 92     /**
1044 06 Feb 08 peter 93        \brief Destructor
1044 06 Feb 08 peter 94
1044 06 Feb 08 peter 95        If SmartPtr is owner and the only owner, underlying pointer is deleted.
1044 06 Feb 08 peter 96      */
1044 06 Feb 08 peter 97     virtual ~SmartPtr()
1044 06 Feb 08 peter 98     {
1048 07 Feb 08 peter 99       detach();
1044 06 Feb 08 peter 100     }
1044 06 Feb 08 peter 101
1044 06 Feb 08 peter 102     /**
1044 06 Feb 08 peter 103        If SmartPtr is owner and the only owner, underlying pointer is deleted.
1044 06 Feb 08 peter 104
1044 06 Feb 08 peter 105        If rhs is owner, lhs become also owner.
1044 06 Feb 08 peter 106      */
1044 06 Feb 08 peter 107     SmartPtr& operator=(const SmartPtr& rhs)
1044 06 Feb 08 peter 108     {
1044 06 Feb 08 peter 109       if (pointee_!=rhs.pointee_){
1048 07 Feb 08 peter 110         detach();
1044 06 Feb 08 peter 111         pointee_ = rhs.pointee_;
1044 06 Feb 08 peter 112         ref_count_= rhs.ref_count_;
1044 06 Feb 08 peter 113         if (ref_count_)
1044 06 Feb 08 peter 114           ++(*ref_count_);
1044 06 Feb 08 peter 115       }
1044 06 Feb 08 peter 116       return *this;
1044 06 Feb 08 peter 117     }
1044 06 Feb 08 peter 118
1044 06 Feb 08 peter 119     /**
1044 06 Feb 08 peter 120        \return underlying pointer
1044 06 Feb 08 peter 121      */
1044 06 Feb 08 peter 122     T* operator->(void) const
1044 06 Feb 08 peter 123     {
1044 06 Feb 08 peter 124       return pointee_;
1044 06 Feb 08 peter 125     }
1044 06 Feb 08 peter 126
1044 06 Feb 08 peter 127     /**
1044 06 Feb 08 peter 128        \return reference to underlying object
1044 06 Feb 08 peter 129      */
1044 06 Feb 08 peter 130     T& operator*(void) const
1044 06 Feb 08 peter 131     {
1044 06 Feb 08 peter 132       return *pointee_;
1044 06 Feb 08 peter 133     }
1044 06 Feb 08 peter 134
1044 06 Feb 08 peter 135   private:
1044 06 Feb 08 peter 136     T* pointee_;
1271 09 Apr 08 peter 137     unsigned int* ref_count_;
1044 06 Feb 08 peter 138
1048 07 Feb 08 peter 139     void detach(void)
1044 06 Feb 08 peter 140     {
1044 06 Feb 08 peter 141       if (ref_count_)
1044 06 Feb 08 peter 142         if (!--(*ref_count_))
1044 06 Feb 08 peter 143           delete pointee_;
2778 19 Jul 12 peter 144     }
1044 06 Feb 08 peter 145   };
1044 06 Feb 08 peter 146
1044 06 Feb 08 peter 147 }}} // of namespace utility, yat, and theplu
1044 06 Feb 08 peter 148 #endif