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