LCOV - code coverage report
Current view: top level - include/crpropa - Referenced.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 41 56 73.2 %
Date: 2024-04-29 14:43:01 Functions: 10 19 52.6 %

          Line data    Source code
       1             : #ifndef CRPROPA_REFERENCED_H
       2             : #define CRPROPA_REFERENCED_H
       3             : 
       4             : #include <cstddef>
       5             : 
       6             : #ifdef DEBUG
       7             : #include <iostream>
       8             : #include <typeinfo>
       9             : #endif
      10             : 
      11             : namespace crpropa {
      12             : /**
      13             :  * \addtogroup Core
      14             :  * @{
      15             :  */
      16             : 
      17             : /**
      18             :  @class Referenced
      19             :  @brief Base class for reference counting
      20             : 
      21             :  A form of memory management is needed to prevent memory leaks when using MPC in Python via SWIG.
      22             :  This base class enables reference counting.
      23             :  Every reference increases the reference counter, every dereference decreases it.
      24             :  When the counter is decreased to 0, the object is deleted.
      25             :  Candidate, Module, MagneticField and Source inherit from this class
      26             :  */
      27             : class Referenced {
      28             : public:
      29             : 
      30     3372446 :         inline Referenced() :
      31     3372425 :                         _referenceCount(0) {
      32             :         }
      33             : 
      34           0 :         inline Referenced(const Referenced&) :
      35           0 :                         _referenceCount(0) {
      36             :         }
      37             : 
      38             :         inline Referenced& operator =(const Referenced&) {
      39             :                 return *this;
      40             :         }
      41             : 
      42             :         inline size_t addReference() const {
      43             :                 int newRef;
      44             : #if defined(OPENMP_3_1)
      45             :                 #pragma omp atomic capture
      46             :                 {newRef = _referenceCount++;}
      47             : #elif defined(__GNUC__)
      48    10919530 :                 newRef = __sync_add_and_fetch(&_referenceCount, 1);
      49             : #else
      50             :                 #pragma omp critical
      51             :                 {newRef = _referenceCount++;}
      52             : #endif
      53     7549422 :                 return newRef;
      54             :         }
      55             : 
      56    10920947 :         inline size_t removeReference() const {
      57             : #ifdef DEBUG
      58             :                 if (_referenceCount == 0)
      59             :                         std::cerr
      60             :                                         << "WARNING: Remove reference from Object with NO references: "
      61             :                                         << typeid(*this).name() << std::endl;
      62             : #endif
      63             :                 int newRef;
      64             : #if defined(OPENMP_3_1)
      65             :                 #pragma omp atomic capture
      66             :                 {newRef = _referenceCount--;}
      67             : #elif defined(__GNUC__)
      68    10920947 :                 newRef = __sync_sub_and_fetch(&_referenceCount, 1);
      69             : #else
      70             :                 #pragma omp critical
      71             :                 {newRef = _referenceCount--;}
      72             : #endif
      73             : 
      74    10920947 :                 if (newRef == 0) {
      75     3370441 :                         delete this;
      76             :                 }
      77    10920947 :                 return newRef;
      78             :         }
      79             : 
      80             :         int removeReferenceNoDelete() const {
      81           0 :                 return --_referenceCount;
      82             :         }
      83             : 
      84             :         inline size_t getReferenceCount() const {
      85           0 :                 return _referenceCount;
      86             :         }
      87             : 
      88             : protected:
      89             : 
      90           0 :         virtual inline ~Referenced() {
      91             : #ifdef DEBUG
      92             :                 if (_referenceCount)
      93             :                         std::cerr << "WARNING: Deleting Object with references: "
      94             :                                         << typeid(*this).name() << std::endl;
      95             : #endif
      96           0 :         }
      97             : 
      98             :         mutable size_t _referenceCount;
      99             : };
     100             : 
     101             : inline void intrusive_ptr_add_ref(Referenced* p) {
     102             :         p->addReference();
     103             : }
     104             : inline void intrusive_ptr_release(Referenced* p) {
     105           0 :         p->removeReference();
     106             : }
     107             : 
     108             : /**
     109             :  @class ref_ptr
     110             :  @brief Referenced pointer
     111             :  */
     112             : template<class T>
     113             : class ref_ptr {
     114             : public:
     115             :         typedef T element_type;
     116             : 
     117         167 :         ref_ptr() :
     118         167 :                         _ptr(0) {
     119             :         }
     120     3331324 :         ref_ptr(T* ptr) :
     121     3333365 :                         _ptr(ptr) {
     122        3307 :                 if (_ptr)
     123             :                         _ptr->addReference();
     124             :         }
     125     7544784 :         ref_ptr(const ref_ptr& rp) :
     126     7544666 :                         _ptr(rp._ptr) {
     127     7544722 :                 if (_ptr)
     128             :                         _ptr->addReference();
     129           2 :         }
     130           4 :         template<class Other> ref_ptr(const ref_ptr<Other>& rp) :
     131           4 :                         _ptr(rp._ptr) {
     132             :                 if (_ptr)
     133             :                         _ptr->addReference();
     134             :         }
     135             : 
     136             :         ~ref_ptr() {
     137    10877181 :                 if (_ptr)
     138    10877254 :                         _ptr->removeReference();
     139             :                 _ptr = 0;
     140    10877176 :         }
     141             : 
     142             :         ref_ptr& operator =(const ref_ptr& rp) {
     143         218 :                 assign(rp);
     144           0 :                 return *this;
     145             :         }
     146             : 
     147             :         template<class Other> ref_ptr& operator =(const ref_ptr<Other>& rp) {
     148             :                 assign(rp);
     149             :                 return *this;
     150             :         }
     151             : 
     152          78 :         inline ref_ptr& operator =(T* ptr) {
     153          78 :                 if (_ptr == ptr)
     154             :                         return *this;
     155             :                 T* tmp_ptr = _ptr;
     156          78 :                 _ptr = ptr;
     157          78 :                 if (_ptr)
     158             :                         _ptr->addReference();
     159          78 :                 if (tmp_ptr)
     160          68 :                         tmp_ptr->removeReference();
     161             :                 return *this;
     162             :         }
     163             : 
     164             :         operator T*() const {
     165      481206 :                 return _ptr;
     166             :         }
     167             : 
     168             :         T& operator*() const {
     169        6615 :                 return *_ptr;
     170             :         }
     171             :         T* operator->() const {
     172     6847260 :                 return _ptr;
     173             :         }
     174             :         T* get() const {
     175          37 :                 return _ptr;
     176             :         }
     177             : 
     178             :         bool operator!() const {
     179           0 :                 return _ptr == 0;
     180             :         } // not required
     181             :         bool valid() const {
     182     5881591 :                 return _ptr != 0;
     183             :         }
     184             : 
     185             :         T* release() {
     186           0 :                 T* tmp = _ptr;
     187           0 :                 if (_ptr)
     188             :                         _ptr->removeReferenceNoDelete();
     189           0 :                 _ptr = 0;
     190             :                 return tmp;
     191             :         }
     192             : 
     193             :         void swap(ref_ptr& rp) {
     194           0 :                 T* tmp = _ptr;
     195           0 :                 _ptr = rp._ptr;
     196           0 :                 rp._ptr = tmp;
     197             :         }
     198             : 
     199             : private:
     200             : 
     201        1319 :         template<class Other> void assign(const ref_ptr<Other>& rp) {
     202        1319 :                 if (_ptr == rp._ptr)
     203             :                         return;
     204             :                 T* tmp_ptr = _ptr;
     205        1315 :                 _ptr = rp._ptr;
     206        1315 :                 if (_ptr)
     207             :                         _ptr->addReference();
     208        1315 :                 if (tmp_ptr)
     209          91 :                         tmp_ptr->removeReference();
     210             :         }
     211             : 
     212             :         template<class Other> friend class ref_ptr;
     213             : 
     214             :         T* _ptr;
     215             : };
     216             : 
     217             : template<class T> inline
     218             : void swap(ref_ptr<T>& rp1, ref_ptr<T>& rp2) {
     219             :         rp1.swap(rp2);
     220             : }
     221             : 
     222             : template<class T> inline T* get_pointer(const ref_ptr<T>& rp) {
     223             :         return rp.get();
     224             : }
     225             : 
     226             : template<class T, class Y> inline ref_ptr<T> static_pointer_cast(
     227             :                 const ref_ptr<Y>& rp) {
     228             :         return static_cast<T*>(rp.get());
     229             : }
     230             : 
     231             : template<class T, class Y> inline ref_ptr<T> dynamic_pointer_cast(
     232             :                 const ref_ptr<Y>& rp) {
     233             :         return dynamic_cast<T*>(rp.get());
     234             : }
     235             : 
     236             : template<class T, class Y> inline ref_ptr<T> const_pointer_cast(
     237             :                 const ref_ptr<Y>& rp) {
     238             :         return const_cast<T*>(rp.get());
     239             : }
     240             : 
     241             : /** @}*/
     242             : } // namespace crpropa
     243             : 
     244             : #endif // CRPROPA_REFERENCED_H

Generated by: LCOV version 1.14