LCOV - code coverage report
Current view: top level - ugbase/common/util - smart_pointer.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 8.7 % 208 18
Test Date: 2026-06-01 23:54:59 Functions: 0.1 % 1890 2

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __SMART_POINTER__
      34              : #define __SMART_POINTER__
      35              : 
      36              : #include <functional>
      37              : #include <cstring>
      38              : 
      39              : /// \addtogroup ugbase_common_util
      40              : /// \{
      41              : 
      42              : ////////////////////////////////////////////////////////////////////////
      43              : ////////////////////////////////////////////////////////////////////////
      44              : //      Policies
      45              : 
      46              : ////////////////////////////////////////////////////////////////////////
      47              : //      FreeDelete
      48              : template <typename T>
      49              : class FreeDelete
      50              : {
      51              :         public:
      52            1 :                 static void free(const T* data) {if(data) delete data;}
      53              : };
      54              : 
      55              : ////////////////////////////////////////////////////////////////////////
      56              : //      FreeDelete
      57              : template <typename T>
      58              : class FreeArrayDelete
      59              : {
      60              :         public:
      61              :                 static void free(const T* data) {if(data) delete[] data;}
      62              : };
      63              : 
      64              : ////////////////////////////////////////////////////////////////////////
      65              : //      FreeRelease
      66              : template <typename T>
      67              : class FreeRelease
      68              : {
      69              :         public:
      70              :                 static void free(const T* data) {data->Release;}
      71              : };
      72              : 
      73              : 
      74              : ////////////////////////////////////////////////////////////////////////
      75              : //      PREDECLARATIONS
      76              : template <class T, template <class TT> class FreePolicy = FreeDelete> class SmartPtr;
      77              : template <class T, template <class TT> class FreePolicy = FreeDelete> class ConstSmartPtr;
      78              : 
      79              : 
      80              : ////////////////////////////////////////////////////////////////////////
      81              : ///     Used to construct empty smart pointers
      82              : /**     SPNULL provides a global const instance.*/
      83              : class NullSmartPtr{
      84              :         public:
      85              :                 NullSmartPtr()  {}
      86              : };
      87              : 
      88              : ///     The equivalent to NULL for smart pointers
      89              : const NullSmartPtr      SPNULL;
      90              : 
      91              : 
      92              : ////////////////////////////////////////////////////////////////////////
      93              : //      SmartPtr
      94              : /**
      95              :  * A Smart Pointer encapsulates a pointer. With each copy
      96              :  * of the SmartPointer a shared reference count is increased and with
      97              :  * each destructor call to a SmartPointer this shared reference count is
      98              :  * decreased. If the shared reference count reaches 0 free as specified in
      99              :  * the FreePolicy is executed on the pointer.
     100              :  *
     101              :  * The FreePolicy has to feature the method free().
     102              :  *
     103              :  * If a const smart pointer is required, use ConstSmartPtr
     104              :  */
     105              : template <typename T, template <class TT> class FreePolicy>
     106              : class SmartPtr
     107              : {
     108              :         friend class ConstSmartPtr<T, FreePolicy>;
     109              :         friend class SmartPtr<void>;
     110              :         friend class ConstSmartPtr<void>;
     111              : 
     112              :         public:
     113              :                 using element_type = T;
     114            1 :                 explicit SmartPtr() : m_ptr(0), m_refCount(0)   {}
     115            1 :                 explicit SmartPtr(T* ptr) : m_ptr(ptr), m_refCount(0)   {if(ptr) m_refCount = new int(1);}
     116            0 :                 SmartPtr(NullSmartPtr) : m_ptr(0), m_refCount(0)        {}
     117            0 :                 SmartPtr(const SmartPtr& sp) : m_ptr(sp.m_ptr), m_refCount(sp.m_refCount)
     118              :                 {
     119            0 :                         if(m_refCount) (*m_refCount)++;
     120              :                 }
     121              : 
     122              :         /**     this template method allows to assign smart-pointers that encapsulate
     123              :          *      derivates of T. Make sure that the pointer-type of TSmartPtr is castable
     124              :          *      to T*.*/
     125              :                 template <class TPtr>
     126            0 :                 SmartPtr(const SmartPtr<TPtr, FreePolicy>& sp) :
     127            0 :                         m_ptr(sp.get_nonconst()),
     128            0 :                         m_refCount(sp.refcount_ptr())
     129              :                 {
     130            0 :                         if(m_refCount) (*m_refCount)++;
     131              :                 }
     132              : 
     133            2 :                 ~SmartPtr() {release();}
     134              : 
     135            0 :                 T* operator->()                      {return m_ptr;}
     136            0 :                 const T* operator->() const  {return m_ptr;}
     137              : 
     138            0 :                 T& operator*()                              {return *m_ptr;}
     139            0 :                 const T& operator*() const  {return *m_ptr;}
     140              : 
     141              :                 SmartPtr& operator=(NullSmartPtr) {
     142            0 :                         if(m_ptr)
     143            0 :                                 release();
     144            0 :                         m_ptr = 0;
     145            0 :                         m_refCount = 0;
     146              :                         return *this;
     147              :                 }
     148              : 
     149            1 :                 SmartPtr& operator=(const SmartPtr& sp) {
     150            1 :                         if(m_ptr)
     151            0 :                                 release();
     152            1 :                         m_ptr = sp.m_ptr;
     153            1 :                         m_refCount = sp.m_refCount;
     154            1 :                         if(m_refCount)
     155            1 :                                 (*m_refCount)++;
     156            1 :                         return *this;
     157              :                 }
     158              : 
     159              :                 template <class TIn>
     160            0 :                 SmartPtr<T, FreePolicy>& operator=(const SmartPtr<TIn, FreePolicy>& sp) {
     161            0 :                         if(m_ptr)
     162            0 :                                 release();
     163            0 :                         m_ptr = sp.get_nonconst();
     164            0 :                         m_refCount = sp.refcount_ptr();
     165            0 :                         if(m_refCount)
     166            0 :                                 (*m_refCount)++;
     167            0 :                         return *this;
     168              :                 }
     169              : 
     170              :                 bool operator==(const SmartPtr& sp) const {
     171              :                         return (this->get() == sp.get());
     172              :                 }
     173              : 
     174              :                 bool operator!=(const SmartPtr& sp) const {
     175              :                         return !(this->operator==(sp));
     176              :                 }
     177              : 
     178              :                 bool operator==(NullSmartPtr) const {
     179            0 :                         return m_ptr == 0;
     180              :                 }
     181              : 
     182              :                 bool operator!=(NullSmartPtr) const {
     183            0 :                         return m_ptr != 0;
     184              :                 }
     185              : 
     186              :                 template <class TPtr>
     187              :                 bool operator==(const ConstSmartPtr<TPtr, FreePolicy>& sp) const {
     188              :                         return (this->get() == sp.get());
     189              :                 }
     190              : 
     191              :                 template <class TPtr>
     192              :                 bool operator!=(const ConstSmartPtr<TPtr, FreePolicy>& sp) const {
     193              :                         return !(this->operator==(sp));
     194              :                 }
     195              : 
     196              :         ///     returns encapsulated pointer
     197            0 :                 T* get()                                {return m_ptr;}
     198              : 
     199              :         ///     returns encapsulated pointer
     200            0 :                 const T* get() const    {return m_ptr;}
     201              : 
     202              :         ///     returns refcount
     203              :                 int refcount() const {if(m_refCount) return *m_refCount; return 0;}
     204              : 
     205              :         ///     returns true if the pointer is valid, false if not.
     206            0 :                 inline bool valid() const       {return m_ptr != NULL;}
     207              : 
     208              :                 // pointer compat -- behave like std::shared_ptr<T>
     209              :                 explicit operator bool() const noexcept { return m_ptr != NULL; }
     210              : 
     211              :         ///     returns true if the pointer is invalid, false if not.
     212            0 :                 inline bool invalid() const     {return m_ptr == NULL;}
     213              : 
     214              :         ///     preforms a dynamic cast
     215              :                 template <class TDest>
     216            0 :                 SmartPtr<TDest, FreePolicy> cast_dynamic() const{
     217            0 :                         TDest* p = dynamic_cast<TDest*>(m_ptr);
     218            0 :                         if(p) return SmartPtr<TDest, FreePolicy>(p, m_refCount);
     219              :                         else return SmartPtr<TDest, FreePolicy>(NULL);
     220              :                 }
     221              : 
     222              :         ///     performs a static cast
     223              :                 template <class TDest>
     224              :                 SmartPtr<TDest, FreePolicy> cast_static() const{
     225            0 :                         TDest* p = static_cast<TDest*>(m_ptr);
     226            0 :                         if(p) return SmartPtr<TDest, FreePolicy>(p, m_refCount);
     227              :                         else return SmartPtr<TDest, FreePolicy>(NULL);
     228              :                 }
     229              : 
     230              :         ///     performs a reinterpret cast
     231              :                 template <class TDest>
     232              :                 SmartPtr<TDest, FreePolicy> cast_reinterpret() const{
     233              :                         TDest* p = reinterpret_cast<TDest*>(m_ptr);
     234              :                         if(p) return SmartPtr<TDest, FreePolicy>(p, m_refCount);
     235              :                         else return SmartPtr<TDest, FreePolicy>(NULL);
     236              :                 }
     237              : 
     238              :         ///
     239              :                 template <class TDest>
     240              :                 bool is_of_type() const
     241              :                 {
     242            0 :                         return dynamic_cast<TDest*>(m_ptr) != NULL;
     243              :                 }
     244              : 
     245              :         ///     performs a const cast
     246              :                 ConstSmartPtr<T, FreePolicy> cast_const() const;
     247              : 
     248              :         ///     WARNING: this method is DANGEROUS!
     249              :         /**     You should only use this constructor if you really know what you're doing!
     250              :          *      The following methods are required for SmartPtr<void> and casts */
     251            0 :                 explicit SmartPtr(T* ptr, int* refCount) : m_ptr(ptr), m_refCount(refCount)
     252              :                 {
     253            0 :                         if(m_refCount)
     254            0 :                                 (*m_refCount)++;
     255              :                 }
     256              : 
     257              :         ///     WARNING: this method is DANGEROUS!
     258              :         /**     This method should never be used since it may be removed in future
     259              :          *      versions of the SmartPtr class.
     260              :          *      It is featured in order to allow to implement a template-constructor
     261              :          *      that casts element-pointers of a smart pointer.
     262              :          *      \{*/
     263            0 :                 int* refcount_ptr() const       {return m_refCount;}
     264              : 
     265            0 :                 T* get_nonconst() const {return m_ptr;}
     266              :         /**     \}      */
     267              : 
     268              :         private:
     269              :         ///     decrements the refCount and frees the encapsulated pointer if required.
     270            2 :                 void release() {
     271            2 :                         if(m_refCount)
     272              :                         {
     273            2 :                                 (*m_refCount)--;
     274            2 :                                 if((*m_refCount) < 1)
     275              :                                 {
     276            1 :                                         delete m_refCount;
     277              :                                         //delete m_ptr;
     278            1 :                                         FreePolicy<T>::free(m_ptr);
     279              :                                 }
     280              :                         }
     281            2 :                 }
     282              : 
     283              :         ///     this release method is required by SmartPtr<void>
     284              :         /**     const void is not really correct here, of course...*/
     285            0 :                 static void free_void_ptr(const void* ptr){
     286            0 :                         FreePolicy<T>::free(reinterpret_cast<const T*>(ptr));
     287            0 :                 }
     288              : 
     289              :         private:
     290              :                 T*              m_ptr;
     291              :                 int*    m_refCount;
     292              : };
     293              : 
     294              : template <typename T, template <class TT> class FreePolicy>
     295              : class ConstSmartPtr
     296              : {
     297              :         friend class ConstSmartPtr<void>;
     298              : 
     299              :         public:
     300              :                 using element_type = T;
     301            0 :                 explicit ConstSmartPtr() : m_ptr(0), m_refCount(0)      {}
     302            0 :                 explicit ConstSmartPtr(const T* ptr) : m_ptr(ptr), m_refCount(0)        {if(ptr) m_refCount = new int(1);}
     303            0 :                 ConstSmartPtr(NullSmartPtr) : m_ptr(0), m_refCount(0)   {}
     304            0 :                 ConstSmartPtr(const ConstSmartPtr& sp) : m_ptr(sp.m_ptr), m_refCount(sp.m_refCount)
     305              :                 {
     306            0 :                         if(m_refCount) (*m_refCount)++;
     307              :                 }
     308              : 
     309              :         /**     this template method allows to assign smart-pointers that encapsulate
     310              :          *      derivates of T. Make sure that the pointer-type of TSmartPtr is castable
     311              :          *      to T*.*/
     312              :                 template <class TPtr>
     313            0 :                 ConstSmartPtr(const SmartPtr<TPtr, FreePolicy>& sp) :
     314            0 :                         m_ptr(sp.get()),
     315            0 :                         m_refCount(sp.refcount_ptr())
     316              :                 {
     317            0 :                         if(m_refCount) (*m_refCount)++;
     318              :                 }
     319              : 
     320              :                 template <class TPtr>
     321            0 :                 ConstSmartPtr(const ConstSmartPtr<TPtr, FreePolicy>& sp) :
     322            0 :                         m_ptr(sp.get()),
     323            0 :                         m_refCount(sp.refcount_ptr())
     324              :                 {
     325            0 :                         if(m_refCount) (*m_refCount)++;
     326              :                 }
     327              : 
     328            0 :                 ~ConstSmartPtr() {release();}
     329              : 
     330            0 :                 const T* operator->() const  {return m_ptr;}
     331              : 
     332            0 :                 const T& operator*() const  {return *m_ptr;}
     333              : 
     334            0 :                 ConstSmartPtr& operator=(const SmartPtr<T, FreePolicy>& sp){
     335            0 :                         if(m_ptr)
     336            0 :                                 release();
     337            0 :                         m_ptr = sp.m_ptr;
     338            0 :                         m_refCount = sp.m_refCount;
     339            0 :                         if(m_refCount)
     340            0 :                                 (*m_refCount)++;
     341            0 :                         return *this;
     342              :                 }
     343              : 
     344              :                 template <class TIn>
     345            0 :                 ConstSmartPtr<T, FreePolicy>& operator=(const SmartPtr<TIn, FreePolicy>& sp){
     346            0 :                         if(m_ptr)
     347            0 :                                 release();
     348            0 :                         m_ptr = sp.get();
     349            0 :                         m_refCount = sp.refcount_ptr();
     350            0 :                         if(m_refCount)
     351            0 :                                 (*m_refCount)++;
     352            0 :                         return *this;
     353              :                 }
     354              : 
     355            0 :                 ConstSmartPtr& operator=(const ConstSmartPtr& sp){
     356            0 :                         if(m_ptr)
     357            0 :                                 release();
     358            0 :                         m_ptr = sp.m_ptr;
     359            0 :                         m_refCount = sp.m_refCount;
     360            0 :                         if(m_refCount)
     361            0 :                                 (*m_refCount)++;
     362            0 :                         return *this;
     363              :                 }
     364              : 
     365              :                 template <class TIn>
     366              :                 ConstSmartPtr<T, FreePolicy>& operator=(const ConstSmartPtr<TIn, FreePolicy>& sp){
     367              :                         if(m_ptr)
     368              :                                 release();
     369              :                         m_ptr = sp.get();
     370              :                         m_refCount = sp.refcount_ptr();
     371              :                         if(m_refCount)
     372              :                                 (*m_refCount)++;
     373              :                         return *this;
     374              :                 }
     375              : 
     376              :                 ConstSmartPtr& operator=(NullSmartPtr){
     377              :                         if(m_ptr)
     378              :                                 release();
     379              :                         m_ptr = 0;
     380              :                         m_refCount = 0;
     381              :                         return *this;
     382              :                 }
     383              : 
     384              :                 bool operator==(const ConstSmartPtr& sp) const{
     385              :                         return (this->get() == sp.get());
     386              :                 }
     387              : 
     388              :                 template <class TPtr>
     389              :                 bool operator==(const SmartPtr<TPtr, FreePolicy>& sp) const{
     390              :                         return (this->get() == sp.get());
     391              :                 }
     392              : 
     393              :                 bool operator==(NullSmartPtr) const{
     394              :                         return m_ptr == 0;
     395              :                 }
     396              : 
     397              :                 bool operator!=(const ConstSmartPtr& sp) const{
     398              :                         return !(this->operator==(sp));
     399              :                 }
     400              : 
     401              :                 template <class TPtr>
     402              :                 bool operator!=(const SmartPtr<TPtr, FreePolicy>& sp) const{
     403              :                         return !(this->operator==(sp));
     404              :                 }
     405              : 
     406              :                 bool operator!=(NullSmartPtr) const{
     407              :                         return m_ptr != NULL;
     408              :                 }
     409              : 
     410            0 :                 const T* get() const    {return m_ptr;}
     411              : 
     412              :                 int refcount() const {if(m_refCount) return *m_refCount; return 0;}
     413              : 
     414              :         ///     returns true if the pointer is valid, false if not.
     415            0 :                 inline bool valid() const       {return m_ptr != NULL;}
     416              : 
     417              :                 // pointer compat -- behave like std::shared_ptr<T>
     418              :                 explicit operator bool() const noexcept { return m_ptr != NULL; }
     419              : 
     420              :         ///     returns true if the pointer is invalid, false if not.
     421            0 :                 inline bool invalid() const     {return m_ptr == NULL;}
     422              : 
     423              :         ///     preforms a dynamic cast
     424              :                 template <class TDest>
     425            0 :                 ConstSmartPtr<TDest, FreePolicy> cast_dynamic() const{
     426            0 :                         const TDest* p = dynamic_cast<const TDest*>(m_ptr);
     427            0 :                         if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
     428              :                         else return ConstSmartPtr<TDest, FreePolicy>(NULL);
     429              :                 }
     430              : 
     431              :         ///     performs a static cast
     432              :                 template <class TDest>
     433              :                 ConstSmartPtr<TDest, FreePolicy> cast_static() const{
     434              :                         const TDest* p = static_cast<const TDest*>(m_ptr);
     435              :                         if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
     436              :                         else return ConstSmartPtr<TDest, FreePolicy>(NULL);
     437              :                 }
     438              : 
     439              :         ///     performs a static cast
     440              :                 template <class TDest>
     441              :                 ConstSmartPtr<TDest, FreePolicy> cast_reinterpret() const{
     442              :                         const TDest* p = reinterpret_cast<const TDest*>(m_ptr);
     443              :                         if(p) return ConstSmartPtr<TDest, FreePolicy>(p, m_refCount);
     444              :                         else return ConstSmartPtr<TDest, FreePolicy>(NULL);
     445              :                 }
     446              : 
     447              :         ///     performs a const cast
     448              :                 SmartPtr<T, FreePolicy> cast_const() const{
     449            0 :                         return SmartPtr<T, FreePolicy>(const_cast<T*>(m_ptr), m_refCount);
     450              :                 }
     451              : 
     452              :         ///
     453              :                 template <class TDest>
     454              :                 bool is_of_type() const
     455              :                 {
     456              :                         return dynamic_cast<TDest*>(m_ptr) != NULL;
     457              :                 }
     458              : 
     459              :         ///     WARNING: this method is DANGEROUS!
     460              :         /**     You should only use this constructor if you really know what you're doing!
     461              :          *      The following methods are required for SmartPtr<void> and casts */
     462            0 :                 explicit ConstSmartPtr(const T* ptr, int* refCount) : m_ptr(ptr), m_refCount(refCount)
     463              :                 {
     464            0 :                         if(m_refCount)
     465            0 :                                 (*m_refCount)++;
     466              :                 }
     467              : 
     468              :         ///     WARNING: this method is dangerous!
     469              :         /**     This method should never be used since it may be removed in future
     470              :          *      versions of the SmartPtr class.
     471              :          *      It is featured in order to allow to implement a template-constructor
     472              :          *      that casts element-pointers of a smart pointer.*/
     473            0 :                 int* refcount_ptr() const {return m_refCount;}
     474              : 
     475              :         private:
     476              :         ///     decrements the refCount and frees the encapsulated pointer if required.
     477            0 :                 void release() {
     478            0 :                         if(m_refCount)
     479              :                         {
     480            0 :                                 (*m_refCount)--;
     481            0 :                                 if((*m_refCount) < 1)
     482              :                                 {
     483            0 :                                         delete m_refCount;
     484              :                                         //delete m_ptr;
     485            0 :                                         FreePolicy<T>::free(m_ptr);
     486              :                                 }
     487              :                         }
     488            0 :                 }
     489              : 
     490              :         //      this release method is required by SmartPtr<void>
     491              :                 static void free_void_ptr(void* ptr){
     492              :                         FreePolicy<T>::free(reinterpret_cast<T*>(ptr));
     493              :                 }
     494              : 
     495              :         private:
     496              :                 const T*        m_ptr;
     497              :                 int*            m_refCount;
     498              : };
     499              : /**     \} */
     500              : 
     501              : 
     502              : ///     performs a const cast
     503              : 
     504              : template <typename T, template <class TT> class FreePolicy>
     505              : inline ConstSmartPtr<T, FreePolicy> SmartPtr<T, FreePolicy>::cast_const() const{
     506              :         return ConstSmartPtr<T, FreePolicy>(*this);
     507              : }
     508              : 
     509              : 
     510              : /**     The SmartPtr<void> is a specialization of the SmartPtr class.
     511              :  * It can only be constructed from an existing SmartPtr or from an
     512              :  * existing SmartPtr<void>. This is crucial to guarantee save
     513              :  * release methods.
     514              :  *
     515              :  * In contrary to the original SmartPtr class, the void specialization
     516              :  * does not feature the -> and * operators. One also can't directly access
     517              :  * the encapsulated pointer.
     518              :  *
     519              :  * If you need a const smart pointer use ConstSmartPtr<void>.
     520              :  *
     521              :  * \todo        add to_smart_ptr_dynamic
     522              :  *
     523              :  */
     524              : template <>
     525              : class SmartPtr<void>
     526              : {
     527              :         friend class ConstSmartPtr<void>;
     528              : 
     529              :         public:
     530              :                 using element_type = void;
     531            0 :                 explicit SmartPtr() : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
     532              : 
     533              :                 SmartPtr(NullSmartPtr) : m_ptr(0), m_refCountPtr(0), m_freeFunc(0)      {}
     534              : 
     535            0 :                 SmartPtr(const SmartPtr<void>& sp) :
     536            0 :                         m_ptr(sp.m_ptr),
     537            0 :                         m_refCountPtr(sp.m_refCountPtr),
     538            0 :                         m_freeFunc(sp.m_freeFunc)
     539              :                 {
     540            0 :                         if(m_refCountPtr) (*m_refCountPtr)++;
     541              :                 }
     542              : 
     543            0 :                 explicit SmartPtr(void* ptr, void (*freeFunc)(const void*)) :
     544            0 :                         m_ptr(ptr),
     545            0 :                         m_refCountPtr(0),
     546            0 :                         m_freeFunc(freeFunc)
     547              :                 {
     548            0 :                         if(ptr) m_refCountPtr = new int(1);
     549              :                 }
     550              : 
     551              :                 template <class T>
     552            0 :                 SmartPtr(const SmartPtr<T>& sp) :
     553            0 :                         m_ptr((void*)sp.m_ptr),
     554            0 :                         m_refCountPtr(sp.m_refCount),
     555            0 :                         m_freeFunc(&SmartPtr<T>::free_void_ptr)
     556              :                 {
     557            0 :                         if(m_refCountPtr) (*m_refCountPtr)++;
     558              :                 }
     559              : 
     560            0 :                 ~SmartPtr() {release();}
     561              : 
     562            0 :                 SmartPtr<void>& operator=(const SmartPtr<void>& sp)
     563              :                 {
     564            0 :                         if(m_ptr)
     565            0 :                                 release();
     566            0 :                         m_ptr = sp.m_ptr;
     567            0 :                         m_refCountPtr = sp.m_refCountPtr;
     568            0 :                         if(m_refCountPtr)
     569            0 :                                 (*m_refCountPtr)++;
     570            0 :                         m_freeFunc = sp.m_freeFunc;
     571            0 :                         return *this;
     572              :                 }
     573              : 
     574              :                 template <class T>
     575              :                 SmartPtr<void>& operator=(const SmartPtr<T>& sp)
     576              :                 {
     577              :                         if(m_ptr)
     578              :                                 release();
     579              :                         m_ptr = sp.m_ptr;
     580              :                         m_refCountPtr = sp.m_refCount;
     581              :                         if(m_refCountPtr)
     582              :                                 (*m_refCountPtr)++;
     583              :                         m_freeFunc = &SmartPtr<T>::free_void_ptr;
     584              :                         return *this;
     585              :                 }
     586              : 
     587              :                 template <class T>
     588              :                 SmartPtr<void>& operator=(NullSmartPtr)
     589              :                 {
     590              :                         if(m_ptr)
     591              :                                 release();
     592              :                         m_ptr = 0;
     593              :                         m_refCountPtr = 0;
     594              :                         m_freeFunc = 0;
     595              :                         return *this;
     596              :                 }
     597              : 
     598              :         ///     Returns a SmartPtr with the specified type and shared reference counting.
     599              :         /**     USE WITH CARE! ONLY COMPATIBLE TYPES SHOULD BE USED*/
     600              :                 template <class T,  template <class TPtr> class TFreePolicy>
     601              :                 SmartPtr<T, TFreePolicy> cast_reinterpret() const {
     602            0 :                         return SmartPtr<T, TFreePolicy>(reinterpret_cast<T*>(m_ptr), m_refCountPtr);
     603              :                 }
     604              : 
     605              :         ///     sets the void* to a different location correspoding to a cast to a new type T
     606              :         /**     !!! WARNING: THIS METHOD IS DANDGEROUS: DO NOT USE IT UNLESS YOU REALLY
     607              :          *               KNOW WHAT YOU ARE DOING !!!
     608              :          */
     609              :                 template <class T, template <class TPtr> class TFreePolicy>
     610              :                 void set_impl(void* ptr)
     611              :                 {
     612            0 :                         m_ptr = ptr;
     613            0 :                         m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
     614              :                 }
     615              : 
     616              :         ///     returns true if the pointer is valid, false if not.
     617            0 :                 inline bool valid() const {return m_ptr != NULL;}
     618              : 
     619              :                 // pointer compat -- behave like std::shared_ptr<T>
     620              :                 explicit operator bool() const noexcept { return m_ptr != NULL; }
     621              : 
     622              :         ///     returns true if the pointer is invalid, false if not.
     623              :                 inline bool invalid() const     {return m_ptr == NULL;}
     624              : 
     625            0 :                 void invalidate()                               {if(valid())    release(); m_ptr = NULL;}
     626              : 
     627            0 :                 void* get()                             {return m_ptr;}
     628              :                 const void* get() const {return m_ptr;}
     629              : 
     630            0 :                 int refcount() const {if(m_refCountPtr) return *m_refCountPtr; return 0;}
     631              : 
     632              :         private:
     633            0 :                 void release() {
     634            0 :                         if(m_refCountPtr)
     635              :                         {
     636            0 :                                 (*m_refCountPtr)--;
     637            0 :                                 if((*m_refCountPtr) < 1)
     638              :                                 {
     639            0 :                                         delete m_refCountPtr;
     640            0 :                                         m_freeFunc(m_ptr);
     641              :                                 }
     642              :                         }
     643            0 :                 }
     644              : 
     645              :                 void* m_ptr;
     646              :                 int* m_refCountPtr;
     647              :                 void (*m_freeFunc)(const void*);
     648              : };
     649              : 
     650              : template <>
     651              : class ConstSmartPtr<void>
     652              : {
     653              :         public:
     654              :                 using element_type = void;
     655            0 :                 explicit ConstSmartPtr() : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
     656              : 
     657              :                 explicit ConstSmartPtr(void* ptr, void (*freeFunc)(const void*)) :
     658              :                         m_ptr(ptr),
     659              :                         m_refCountPtr(0),
     660              :                         m_freeFunc(freeFunc)
     661              :                 {
     662              :                         if(ptr) m_refCountPtr = new int(1);
     663              :                 }
     664              : 
     665              :                 ConstSmartPtr(NullSmartPtr) : m_ptr(0), m_refCountPtr(0), m_freeFunc(0) {}
     666              : 
     667              :                 ConstSmartPtr(const SmartPtr<void>& sp) :
     668            0 :                         m_ptr(sp.m_ptr),
     669            0 :                         m_refCountPtr(sp.m_refCountPtr),
     670            0 :                         m_freeFunc(sp.m_freeFunc)
     671              :                 {
     672            0 :                         if(m_refCountPtr) (*m_refCountPtr)++;
     673              :                 }
     674              : 
     675            0 :                 ConstSmartPtr(const ConstSmartPtr<void>& sp) :
     676            0 :                         m_ptr(sp.m_ptr),
     677            0 :                         m_refCountPtr(sp.m_refCountPtr),
     678            0 :                         m_freeFunc(sp.m_freeFunc)
     679              :                 {
     680            0 :                         if(m_refCountPtr) (*m_refCountPtr)++;
     681              :                 }
     682              : 
     683              :                 template <class T, template <class TPtr> class TFreePolicy>
     684              :                 ConstSmartPtr(const SmartPtr<T, TFreePolicy>& sp) :
     685              :                         m_ptr((void*)sp.m_ptr),
     686              :                         m_refCountPtr(sp.m_refCount),
     687              :                         m_freeFunc(&SmartPtr<T, TFreePolicy>::free_void_ptr)
     688              :                 {
     689              :                         if(m_refCountPtr) (*m_refCountPtr)++;
     690              :                 }
     691              : 
     692              :                 template <class T, template <class TPtr> class TFreePolicy>
     693            0 :                 ConstSmartPtr(const ConstSmartPtr<T, TFreePolicy>& sp) :
     694            0 :                         m_ptr((void*)sp.m_ptr),
     695            0 :                         m_refCountPtr(sp.m_refCount),
     696            0 :                         m_freeFunc(&SmartPtr<T, TFreePolicy>::free_void_ptr)
     697              :                 {
     698            0 :                         if(m_refCountPtr) (*m_refCountPtr)++;
     699              :                 }
     700              : 
     701            0 :                 ~ConstSmartPtr() {release();}
     702              : 
     703            0 :                 ConstSmartPtr<void>& operator=(const SmartPtr<void>& sp)
     704              :                 {
     705            0 :                         if(m_ptr)
     706            0 :                                 release();
     707            0 :                         m_ptr = sp.m_ptr;
     708            0 :                         m_refCountPtr = sp.m_refCountPtr;
     709            0 :                         if(m_refCountPtr)
     710            0 :                                 (*m_refCountPtr)++;
     711            0 :                         m_freeFunc = sp.m_freeFunc;
     712            0 :                         return *this;
     713              :                 }
     714              : 
     715            0 :                 ConstSmartPtr<void>& operator=(const ConstSmartPtr<void>& sp)
     716              :                 {
     717            0 :                         if(m_ptr)
     718            0 :                                 release();
     719            0 :                         m_ptr = sp.m_ptr;
     720            0 :                         m_refCountPtr = sp.m_refCountPtr;
     721            0 :                         if(m_refCountPtr)
     722            0 :                                 (*m_refCountPtr)++;
     723            0 :                         m_freeFunc = sp.m_freeFunc;
     724            0 :                         return *this;
     725              :                 }
     726              : 
     727              :                 template <class T, template <class TPtr> class TFreePolicy>
     728              :                 ConstSmartPtr<void>& operator=(const SmartPtr<T, TFreePolicy>& sp)
     729              :                 {
     730              :                         if(m_ptr)
     731              :                                 release();
     732              :                         m_ptr = sp.m_ptr;
     733              :                         m_refCountPtr = sp.m_refCount;
     734              :                         if(m_refCountPtr)
     735              :                                 (*m_refCountPtr)++;
     736              :                         m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
     737              :                         return *this;
     738              :                 }
     739              : 
     740              :                 template <class T, template <class TPtr> class TFreePolicy>
     741              :                 ConstSmartPtr<void>& operator=(const ConstSmartPtr<T, TFreePolicy>& sp)
     742              :                 {
     743              :                         if(m_ptr)
     744              :                                 release();
     745              :                         m_ptr = sp.m_ptr;
     746              :                         m_refCountPtr = sp.m_refCount;
     747              :                         if(m_refCountPtr)
     748              :                                 (*m_refCountPtr)++;
     749              :                         m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
     750              :                         return *this;
     751              :                 }
     752              : 
     753              :                 ConstSmartPtr<void>& operator=(NullSmartPtr)
     754              :                 {
     755              :                         if(m_ptr)
     756              :                                 release();
     757              :                         m_ptr = 0;
     758              :                         m_refCountPtr = 0;
     759              :                         m_freeFunc = 0;
     760              :                         return *this;
     761              :                 }
     762              : 
     763              :         ///     Returns a SmartPtr with the specified type and shared reference counting.
     764              :         /**     USE WITH CARE! ONLY COMPATIBLE TYPES SHOULD BE USED*/
     765              :                 template <class T, template <class TPtr> class TFreePolicy>
     766              :                 ConstSmartPtr<T, TFreePolicy> cast_reinterpret() const{
     767            0 :                         return ConstSmartPtr<T, TFreePolicy>(reinterpret_cast<const T*>(m_ptr), m_refCountPtr);
     768              :                 }
     769              : 
     770              :         ///     sets the void* to a different location correspoding to a cast to a new type T
     771              :         /**     !!! WARNING: THIS METHOD IS DANDGEROUS: DO NOT USE IT UNLESS YOU REALLY
     772              :          *               KNOW WHAT YOU ARE DOING !!!
     773              :          */
     774              :                 template <class T, template <class TPtr> class TFreePolicy>
     775              :                 void set_impl(const void* ptr)
     776              :                 {
     777            0 :                         m_ptr = ptr;
     778            0 :                         m_freeFunc = &SmartPtr<T, TFreePolicy>::free_void_ptr;
     779              :                 }
     780              : 
     781              :         ///     returns true if the pointer is valid, false if not.
     782            0 :                 inline bool valid() const {return m_ptr != NULL;}
     783              : 
     784              :                 // pointer compat -- behave like std::shared_ptr<T>
     785              :                 explicit operator bool() const noexcept { return m_ptr != NULL; }
     786              : 
     787              :         ///     returns true if the pointer is invalid, false if not.
     788              :                 inline bool invalid() const     {return m_ptr == NULL;}
     789              : 
     790            0 :                 void invalidate()                               {if(valid())    release(); m_ptr = NULL;}
     791              : 
     792            0 :                 const void* get() const {return m_ptr;}
     793              : 
     794            0 :                 int refcount() const {if(m_refCountPtr) return *m_refCountPtr; return 0;}
     795              : 
     796              :         private:
     797            0 :                 void release() {
     798            0 :                         if(m_refCountPtr)
     799              :                         {
     800            0 :                                 (*m_refCountPtr)--;
     801            0 :                                 if((*m_refCountPtr) < 1)
     802              :                                 {
     803            0 :                                         delete m_refCountPtr;
     804            0 :                                         m_freeFunc(const_cast<void*>(m_ptr));
     805              :                                 }
     806              :                         }
     807            0 :                 }
     808              : 
     809              :                 const void* m_ptr;
     810              :                 int* m_refCountPtr;
     811              :                 void (*m_freeFunc)(const void*);
     812              : };
     813              : 
     814              : 
     815              : 
     816              : namespace std
     817              : {
     818              :         template <class T, template <class TPtr> class TFreePolicy>
     819              :         struct less<SmartPtr<T, TFreePolicy> >
     820              : #if (__cplusplus < 201103L)
     821              :         : public binary_function<SmartPtr<T, TFreePolicy>, SmartPtr<T, TFreePolicy>, bool>
     822              : #endif
     823              :         {
     824              :                 bool operator()(const SmartPtr<T, TFreePolicy>& lhs,
     825              :                                                 const SmartPtr<T, TFreePolicy>& rhs) const
     826              :                 {
     827              :                         return less<T*>()(lhs.get(), rhs.get());
     828              :                 }
     829              :         };
     830              : }
     831              : 
     832              : 
     833              : ////////////////////////////////////////////////////////////////////////
     834              : //      Creation helper for SmartPtr
     835              : ////////////////////////////////////////////////////////////////////////
     836              : 
     837              : /// returns a SmartPtr for the passed raw pointer
     838              : template <typename T, template <class TT> class FreePolicy>
     839              : SmartPtr<T, FreePolicy> make_sp(T* inst)
     840              : {
     841              :         return SmartPtr<T, FreePolicy>(inst);
     842              : }
     843              : 
     844              : /// returns a SmartPtr for the passed raw pointer
     845              : template <typename T>
     846              : SmartPtr<T> make_sp(T* inst)
     847              : {
     848              :         return SmartPtr<T>(inst);
     849              : }
     850              : 
     851              : // boost::pointee has become deprecated. In C++11, it should be replaced by  
     852              : // std::pointer_traits<my_ptr<T>>::element_type
     853              : 
     854              : 
     855              : // end group ugbase_common_util
     856              : /// \}
     857              : 
     858              : #endif
        

Generated by: LCOV version 2.0-1