LCOV - code coverage report
Current view: top level - include/crpropa - Referenced.h (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 68.1 % 47 32
Test Date: 2026-07-30 13:07:59 Functions: 54.5 % 22 12

            Line data    Source code
       1              : #ifndef CRPROPA_REFERENCED_H
       2              : #define CRPROPA_REFERENCED_H
       3              : 
       4              : #include <cstddef>
       5              : #include <type_traits>
       6              : 
       7              : #ifdef DEBUG
       8              : #include <iostream>
       9              : #include <typeinfo>
      10              : #endif
      11              : 
      12              : namespace crpropa {
      13              : /**
      14              :  * \addtogroup Core
      15              :  * @{
      16              :  */
      17              : 
      18              : /**
      19              :  @class Referenced
      20              :  @brief Base class for reference counting
      21              : 
      22              :  A form of memory management is needed to prevent memory leaks when using MPC in Python via SWIG.
      23              :  This base class enables reference counting.
      24              :  Every reference increases the reference counter, every dereference decreases it.
      25              :  When the counter is decreased to 0, the object is deleted.
      26              :  Candidate, Module, MagneticField and Source inherit from this class
      27              :  */
      28              : class Referenced {
      29              :         public:
      30              : 
      31      3377708 :         constexpr Referenced() noexcept :
      32      3377688 :                         _referenceCount(0) {
      33              :         }
      34              : 
      35            0 :         constexpr Referenced(const Referenced&) noexcept :
      36            0 :                         _referenceCount(0) {
      37              :         }
      38              : 
      39              :         constexpr Referenced& operator =(const Referenced&) noexcept {
      40              :                 return *this;
      41              :         }
      42              : 
      43              :         inline size_t addReference() const noexcept {
      44              :                 int newRef;
      45              :                 #if defined(OPENMP_3_1)
      46              :                         #pragma omp atomic capture
      47              :                         {newRef = _referenceCount++;}
      48              :                 #elif defined(__GNUC__)
      49     10945715 :                         newRef = __sync_add_and_fetch(&_referenceCount, 1);
      50              :                 #else
      51              :                         #pragma omp critical(newRef)
      52              :                         {newRef = _referenceCount++;}
      53              :                 #endif
      54      7570701 :                 return newRef;
      55              :         }
      56              : 
      57              :         #ifdef DEBUG
      58              :         inline size_t removeReference() const {
      59              :                 if (_referenceCount == 0)
      60              :                         std::cerr
      61              :                                         << "WARNING: Remove reference from Object with NO references: "
      62              :                                         << typeid(*this).name() << std::endl;
      63              :         #else
      64     10947383 :         inline size_t removeReference() const noexcept {
      65              :         #endif
      66              :                 int newRef;
      67              :                 #if defined(OPENMP_3_1)
      68              :                         #pragma omp atomic capture
      69              :                         {newRef = _referenceCount--;}
      70              :                 #elif defined(__GNUC__)
      71     10947383 :                         newRef = __sync_sub_and_fetch(&_referenceCount, 1);
      72              :                 #else
      73              :                         #pragma omp critical(newRef)
      74              :                         {newRef = _referenceCount--;}
      75              :                 #endif
      76              : 
      77     10947383 :                 if (newRef == 0) {
      78      3375656 :                         delete this;
      79              :                 }
      80     10947383 :                 return newRef;
      81              :         }
      82              : 
      83              :         inline int removeReferenceNoDelete() const noexcept {
      84            0 :                 return --_referenceCount;
      85              :         }
      86              : 
      87              :         inline size_t getReferenceCount() const noexcept {
      88            0 :                 return _referenceCount;
      89              :         }
      90              : 
      91              :         protected:
      92              : 
      93            0 :         virtual inline ~Referenced() {
      94              :                 #ifdef DEBUG
      95              :                 if (_referenceCount)
      96              :                         std::cerr << "WARNING: Deleting Object with references: "
      97              :                                         << typeid(*this).name() << std::endl;
      98              :                 #endif
      99            0 :         }
     100              : 
     101              :         mutable size_t _referenceCount;
     102              : };
     103              : 
     104              : inline void intrusive_ptr_add_ref(Referenced* p) {
     105              :         p->addReference();
     106              : }
     107              : inline void intrusive_ptr_release(Referenced* p) {
     108            0 :         p->removeReference();
     109              : }
     110              : 
     111              : // helper Reference class functions, which function to use is decided at compile time!
     112              : template<class T>
     113              : typename std::enable_if_t<std::is_base_of<Referenced, T>::value>
     114              : inline addReferenceIf(T* ptr) noexcept {
     115      7570721 :         if (ptr) ptr->addReference();
     116              : }
     117              : template<class T>
     118              : typename std::enable_if_t<!std::is_base_of<Referenced, T>::value>
     119              : inline addReferenceIf(T* ptr) noexcept {}
     120              : 
     121              : template<class T>
     122              : typename std::enable_if_t<std::is_base_of<Referenced, T>::value>
     123              : inline removeReferenceIf(T* ptr) noexcept {
     124     10905073 :         if (ptr) ptr->removeReference();
     125              : }
     126              : template<class T>
     127              : typename std::enable_if_t<!std::is_base_of<Referenced, T>::value>
     128              : inline removeReferenceIf(T* ptr) noexcept {}
     129              : 
     130              : template<class T>
     131              : typename std::enable_if_t<std::is_base_of<Referenced, T>::value>
     132              : inline removeReferenceNoDeleteIf(T* ptr) noexcept {
     133            0 :         if (ptr) ptr->removeReferenceNoDelete();
     134              : }
     135              : template<class T>
     136              : typename std::enable_if_t<!std::is_base_of<Referenced, T>::value>
     137              : inline removeReferenceNoDeleteIf(T* ptr) noexcept {}
     138              : 
     139              : /**
     140              :  @class ref_ptr
     141              :  @brief Referenced pointer
     142              : 
     143              :  This class manages the memory of objects that inherit the class Referenced.
     144              :  Every other object is not managed but instead treated as raw pointer and should
     145              :  be managed by the original variable owner.
     146              :  */
     147              : template<class T>
     148              : class ref_ptr {
     149              : public:
     150              :         typedef T element_type;
     151              : 
     152              :         /** Default Constructor */
     153          305 :         constexpr ref_ptr() noexcept : _ptr(0) {}
     154              :         #ifndef SWIG 
     155              :         /** Constructor from reference
     156              :          * Use this constructor if you want to use a stack pointer,
     157              :          * so every pointer not created with a new operator.
     158              :          */
     159              :         inline ref_ptr(T& ref) noexcept : _ptr(&ref) {}
     160              :         #endif
     161              :         /** Constructor from pointer
     162              :          * Should not be used with stack pointer,
     163              :          * so every pointer not created with a new operator.
     164              :          */
     165      3338561 :         inline ref_ptr(T* ptr) noexcept : _ptr(ptr) {
     166              :                 addReferenceIf(_ptr);
     167              :         }
     168              :         /** Constructor from ref_ptr with same template type */
     169      7566034 :         inline ref_ptr(const ref_ptr& rp) noexcept : _ptr(rp._ptr) {
     170              :                 addReferenceIf(_ptr);
     171            2 :         }
     172              :         /** Constructor from ref_ptr with other template type, must be convertable */
     173            4 :         template<class Other> inline ref_ptr(const ref_ptr<Other>& rp) noexcept : _ptr(rp._ptr) {
     174              :                 addReferenceIf(_ptr);
     175              :         }
     176              : 
     177              :         /** destructor */
     178              :         inline ~ref_ptr() noexcept {
     179      7570480 :                 removeReferenceIf(_ptr);
     180              :                 _ptr = 0;
     181      6674290 :         }
     182              : 
     183              :         /** Assign operator for ref_ptr with same template type */
     184              :         inline ref_ptr& operator =(const ref_ptr& rp) noexcept {
     185          253 :                 assign(rp);
     186            0 :                 return *this;
     187              :         }
     188              :         /** Assign operator for ref_ptr with other template type, must be convertable */
     189              :         template<class Other> inline ref_ptr& operator =(const ref_ptr<Other>& rp) noexcept {
     190              :                 assign(rp);
     191              :                 return *this;
     192              :         }
     193              :         /** Assign operator for pointer, do not assign stack pointer */
     194          158 :         inline ref_ptr& operator =(T* ptr) noexcept {
     195          397 :                 if (_ptr != ptr) {
     196              :                         T* tmp_ptr = _ptr;
     197          158 :                         _ptr = ptr;
     198              :                         addReferenceIf(_ptr);
     199              :                         removeReferenceIf(tmp_ptr);
     200              :                 }
     201          158 :                 return *this;
     202              :         }
     203              :         #ifndef SWIG
     204              :         /** Assign operator for stack references */
     205              :         inline ref_ptr& operator =(T& ref) noexcept {
     206              :                 if (_ptr != &ref)
     207              :                         _ptr = &ref;
     208              :                 return *this;
     209              :         }
     210              :         #endif
     211              : 
     212              :         inline operator T*() const noexcept {
     213       481152 :                 return _ptr;
     214              :         }
     215              : 
     216              :         inline T& operator*() const noexcept {
     217         6484 :                 return *_ptr;
     218              :         }
     219              :         inline T* operator->() const noexcept {
     220      6174249 :                 return _ptr;
     221              :         }
     222              :         inline T* get() const {
     223           37 :                 return _ptr;
     224              :         }
     225              : 
     226              :         inline bool operator!() const noexcept {
     227            0 :                 return _ptr == 0;
     228              :         } // not required
     229              :         inline bool valid() const noexcept {
     230      5881542 :                 return _ptr != 0;
     231              :         }
     232              : 
     233              :         inline T* release() noexcept {
     234            0 :                 T* tmp = _ptr;
     235              :                 removeReferenceNoDeleteIf(_ptr);
     236            0 :                 _ptr = 0;
     237              :                 return tmp;
     238              :         }
     239              : 
     240              :         inline void swap(ref_ptr& rp) noexcept {
     241            0 :                 T* tmp = _ptr;
     242            0 :                 _ptr = rp._ptr;
     243            0 :                 rp._ptr = tmp;
     244              :         }
     245              : 
     246              : private:
     247              : 
     248         1354 :         template<class Other> inline void assign(const ref_ptr<Other>& rp) noexcept {
     249         1354 :                 if (_ptr != rp._ptr) {
     250              :                         T* tmp_ptr = _ptr;
     251         1328 :                         _ptr = rp._ptr;
     252              :                         addReferenceIf(_ptr);
     253              :                         removeReferenceIf(tmp_ptr);
     254              :                 }
     255         1354 :         }
     256              : 
     257              :         template<class Other> friend class ref_ptr;
     258              : 
     259              :         T* _ptr;
     260              : };
     261              : 
     262              : template<class T> inline
     263              : void swap(ref_ptr<T>& rp1, ref_ptr<T>& rp2) {
     264              :         rp1.swap(rp2);
     265              : }
     266              : 
     267              : template<class T> inline T* get_pointer(const ref_ptr<T>& rp) {
     268              :         return rp.get();
     269              : }
     270              : 
     271              : template<class T, class Y> inline ref_ptr<T> static_pointer_cast(
     272              :                 const ref_ptr<Y>& rp) {
     273              :         return static_cast<T*>(rp.get());
     274              : }
     275              : 
     276              : template<class T, class Y> inline ref_ptr<T> dynamic_pointer_cast(
     277              :                 const ref_ptr<Y>& rp) {
     278              :         return dynamic_cast<T*>(rp.get());
     279              : }
     280              : 
     281              : template<class T, class Y> inline ref_ptr<T> const_pointer_cast(
     282              :                 const ref_ptr<Y>& rp) {
     283              :         return const_cast<T*>(rp.get());
     284              : }
     285              : 
     286              : /** @}*/
     287              : } // namespace crpropa
     288              : 
     289              : #endif // CRPROPA_REFERENCED_H
        

Generated by: LCOV version 2.0-1