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 3373373 : inline Referenced() :
31 3373352 : _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 10922282 : newRef = __sync_add_and_fetch(&_referenceCount, 1);
49 : #else
50 : #pragma omp critical(newRef)
51 : {newRef = _referenceCount++;}
52 : #endif
53 7551177 : return newRef;
54 : }
55 :
56 10923612 : 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 10923612 : newRef = __sync_sub_and_fetch(&_referenceCount, 1);
69 : #else
70 : #pragma omp critical(newRef)
71 : {newRef = _referenceCount--;}
72 : #endif
73 :
74 10923612 : if (newRef == 0) {
75 3371342 : delete this;
76 : }
77 10923612 : 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 174 : ref_ptr() :
118 174 : _ptr(0) {
119 : }
120 3332219 : ref_ptr(T* ptr) :
121 3334260 : _ptr(ptr) {
122 3307 : if (_ptr)
123 : _ptr->addReference();
124 : }
125 7546539 : ref_ptr(const ref_ptr& rp) :
126 7546425 : _ptr(rp._ptr) {
127 7546474 : 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 7551001 : if (_ptr)
138 10879914 : _ptr->removeReference();
139 : _ptr = 0;
140 10879832 : }
141 :
142 : ref_ptr& operator =(const ref_ptr& rp) {
143 221 : 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 481154 : return _ptr;
166 : }
167 :
168 : T& operator*() const {
169 6617 : return *_ptr;
170 : }
171 : T* operator->() const {
172 6153353 : 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 5881544 : 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 1322 : template<class Other> void assign(const ref_ptr<Other>& rp) {
202 1322 : if (_ptr == rp._ptr)
203 : return;
204 : T* tmp_ptr = _ptr;
205 1318 : _ptr = rp._ptr;
206 1318 : if (_ptr)
207 : _ptr->addReference();
208 1318 : 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
|