Fork me on GitHub

source: git/external/fastjet/SharedPtr.hh@ 7b0e00c

Last change on this file since 7b0e00c was 35cdc46, checked in by Pavel Demin <demin@…>, 10 years ago

upgrade FastJet to version 3.1.0-beta.1, upgrade Nsubjettiness to version 2.1.0, add SoftKiller version 1.0.0

  • Property mode set to 100644
File size: 12.9 KB
Line 
1#ifndef __FASTJET_SHARED_PTR_HH__
2#define __FASTJET_SHARED_PTR_HH__
3
4//FJSTARTHEADER
5// $Id: SharedPtr.hh 3433 2014-07-23 08:17:03Z salam $
6//
7// Copyright (c) 2005-2014, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
8//
9//----------------------------------------------------------------------
10// This file is part of FastJet.
11//
12// FastJet is free software; you can redistribute it and/or modify
13// it under the terms of the GNU General Public License as published by
14// the Free Software Foundation; either version 2 of the License, or
15// (at your option) any later version.
16//
17// The algorithms that underlie FastJet have required considerable
18// development. They are described in the original FastJet paper,
19// hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
20// FastJet as part of work towards a scientific publication, please
21// quote the version you use and include a citation to the manual and
22// optionally also to hep-ph/0512210.
23//
24// FastJet is distributed in the hope that it will be useful,
25// but WITHOUT ANY WARRANTY; without even the implied warranty of
26// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27// GNU General Public License for more details.
28//
29// You should have received a copy of the GNU General Public License
30// along with FastJet. If not, see <http://www.gnu.org/licenses/>.
31//----------------------------------------------------------------------
32//FJENDHEADER
33
34#include "fastjet/internal/base.hh"
35#include <cstdlib> // for NULL!!!
36
37// for testing purposes, the following define makes it possible
38// for our SharedPtr simply to be derived from the STL TR1 one.
39// #define __FASTJET_USETR1SHAREDPTR
40
41#ifdef __FASTJET_USETR1SHAREDPTR
42#include <tr1/memory>
43#endif // __FASTJET_USETR1SHAREDPTR
44
45FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
46
47#ifdef __FASTJET_USETR1SHAREDPTR
48
49/// @ingroup advanced_usage
50/// \class SharedPtr
51/// replaces our shared pointer with the TR1 one (for testing purpose)
52///
53/// for testing purposes, it can be useful to replace our home-made
54/// SharedPtr with the standard library one. Having a class derived
55/// from the standard one is way of arranging for this to happen.
56///
57/// The other way of working this is a template class with an
58/// internal typedef (http://bytes.com/topic/c/answers/60312-typedef-template)
59/// since templated typedefs don't work in standard C++
60///
61/// Note that some facilities that are present in the FastJet shared
62/// pointer (resetting use-count) are not handled by the TR1 shared
63/// pointer; and the FastJet SharedPtr has a different underlying data
64/// structure from the TR1 shared pointer, which prevents us from
65/// implementing some of TR1 features (notably assignment from shared
66/// pointers to a derived class).
67template<class T>
68class SharedPtr : public std::tr1::shared_ptr<T> {
69public:
70 SharedPtr() : std::tr1::shared_ptr<T>() {}
71 SharedPtr(T * t) : std::tr1::shared_ptr<T>(t) {}
72 SharedPtr(const SharedPtr<T> & t) : std::tr1::shared_ptr<T>(t) {}
73 // for some reason operator() doesn't get inherited
74 inline operator bool() const {return (this->get()!=NULL);}
75 /// return the pointer we're pointing to
76 T* operator ()() const{
77 return this->get(); // automatically returns NULL when out-of-scope
78 }
79};
80
81
82#else // __FASTJET_USETR1SHAREDPTR
83
84/**
85 * @ingroup advanced_usage
86 * \class SharedPtr
87 * an implementation of C++0x shared pointers (or boost's)
88 *
89 * this class implements a smart pointer, based on the shared+ptr
90 * proposal. A description of shared_ptr can be found in Section 2.2.3
91 * of the first C++ Technical Report (TR1)
92 * http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf
93 * or, alternatively, on the Boost C++ library website at
94 * http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
95 *
96 * Our implementation is compatible with both of these apart from a
97 * series of members and functions that have not been implemented:
98 * - conversion from weak and auto pointers
99 * - support for deleters and allocators
100 * - static, constant and dynamic casts
101 * - constructor and assignment sharing ownership with a shared
102 * pointer r but storing a different pointer than r (needed for the
103 * previous item)
104 * In the last 2 cases, their implementation would require storing two
105 * pointers for every copies of the shared pointer, while our
106 * implementation only needs one. We did not implement then since we
107 * want to limit as much as possible memory and time consumption, and
108 * can easily avoid (at least for our needs so far) the casts.
109 *
110 * We also add the possibility to force an update of the count.
111 *
112 * The class has been tested against the existing boost (v1.42)
113 * implementation (for the parts that we have implemented).
114 */
115template<class T>
116class SharedPtr{
117public:
118 /// forward declaration of the counting container
119 class __SharedCountingPtr;
120
121 /// default ctor
122 SharedPtr() : _ptr(NULL){}
123
124 /// initialise with the main data
125 /// \param t : the object we want a smart pointer to
126 template<class Y> explicit SharedPtr(Y* ptr){
127 _ptr = new __SharedCountingPtr(ptr);
128 }
129
130 /// overload the copy ctor so that it updates count
131 /// \param share : the object we want to copy
132 SharedPtr(SharedPtr const & share) : _ptr(share._get_container()){
133 if (_ptr!=NULL) ++(*_ptr);
134 }
135 // old version
136 // SharedPtr(SharedPtr const & share) : _ptr(NULL){
137 // reset(share);
138 // }
139
140 // will not work with the current structure
141 // /// overload the copy ctor so that it updates count
142 // /// \param share : the object we want to copy
143 // template<class Y> SharedPtr(SharedPtr<Y> const & share) : _ptr(NULL){
144 // reset(share);
145 // }
146
147 /// default dtor
148 ~SharedPtr(){
149 // make sure the object has been allocated
150 if (_ptr==NULL) return;
151
152 _decrease_count();
153 }
154
155 /// reset the pointer to default value (NULL)
156 void reset(){
157 // // if we already are pointing to sth, be sure to decrease its count
158 // if (_ptr!=NULL) _decrease_count();
159 // _ptr = NULL;
160 SharedPtr().swap(*this);
161 }
162
163 // will not work with the current structure
164 /// reset from a pointer
165 template<class Y> void reset(Y * ptr){
166 // // if we already are pointing to sth, be sure to decrease its count
167 // if (_ptr!=NULL) _decrease_count();
168 //
169 // _ptr = new __SharedCountingPtr(ptr);
170 SharedPtr(ptr).swap(*this);
171 }
172
173 // not part of the standard
174 /// do a smart copy
175 /// \param share : the object we want to copy
176 /// Q? Do we need a non-template<Y> version as for the ctor and the assignment?
177 template<class Y> void reset(SharedPtr<Y> const & share){
178 //void reset(SharedPtr const & share){
179 // if we already are pointing to sth, be sure to decrease its count
180 if (_ptr!=NULL){
181 // in the specific case where we're having the same
182 // share,reset() has actually no effect. However if *this is the
183 // only instance still alive (implying share==*this) bringing
184 // the count down to 0 and deleting the object will not have the
185 // expected effect. So we just avoid that situation explicitly
186 if (_ptr == share._get_container()) return;
187
188 _decrease_count();
189 }
190
191 // Watch out: if share is empty, construct an empty shared_ptr
192
193 // copy the container
194 _ptr = share._get_container(); // Note: automatically set it to NULL if share is empty
195
196 if (_ptr!=NULL) ++(*_ptr);
197 }
198
199 /// overload the = operator so that it updates count
200 /// \param share : the object we want to copy
201 SharedPtr& operator=(SharedPtr const & share){
202 reset(share);
203 return *this;
204 }
205
206 /// overload the = operator so that it updates count
207 /// \param share : the object we want to copy
208 template<class Y> SharedPtr& operator=(SharedPtr<Y> const & share){
209 reset(share);
210 return *this;
211 }
212
213 /// return the pointer we're pointing to
214 T* operator ()() const{
215 if (_ptr==NULL) return NULL;
216 return _ptr->get(); // automatically returns NULL when out-of-scope
217 }
218
219 /// indirection, get a reference to the stored pointer
220 ///
221 /// !!! WATCH OUT
222 /// It fails to check the requirement that the stored pointer must
223 /// not be NULL!! So you need explicitly to check the validity in
224 /// your code
225 inline T& operator*() const{
226 return *(_ptr->get());
227 }
228
229 /// indirection, get the stored pointer
230 ///
231 /// !!! WATCH OUT
232 /// It fails to check the requirement that the stored pointer must
233 /// not be NULL!! So you need explicitly to check the validity in
234 /// your code
235 inline T* operator->() const{
236 if (_ptr==NULL) return NULL;
237 return _ptr->get();
238 }
239
240 /// get the stored pointer
241 inline T* get() const{
242 if (_ptr==NULL) return NULL;
243 return _ptr->get();
244 }
245
246 /// check if the instance is unique
247 inline bool unique() const{
248 return (use_count()==1);
249 }
250
251 /// return the number of counts
252 inline long use_count() const{
253 if (_ptr==NULL) return 0;
254 return _ptr->use_count(); // automatically returns NULL when out-of-scope
255 }
256
257 /// conversion to bool
258 /// This will allow you to use the indirection nicely
259 inline operator bool() const{
260 return (get()!=NULL);
261 }
262
263 /// exchange the content of the two pointers
264 inline void swap(SharedPtr & share){
265 __SharedCountingPtr* share_container = share._ptr;
266 share._ptr = _ptr;
267 _ptr = share_container;
268 }
269
270 /// force the count to be set to a specified value
271 /// \param count the value that we need to reset to
272 void set_count(const long & count){
273 if (_ptr==NULL) return;
274 _ptr->set_count(count);
275 }
276
277 /**
278 * \if internal_doc
279 * \class __SharedCountingPtr
280 * A reference-counting pointer
281 *
282 * This is implemented as a container for that pointer together with
283 * reference counting.
284 * The pointer is deleted when the number of counts goes to 0;
285 * \endif
286 */
287 class __SharedCountingPtr{
288 public:
289 /// default ctor
290 __SharedCountingPtr() : _ptr(NULL), _count(0){}
291
292 /// ctor with initialisation
293 template<class Y> explicit __SharedCountingPtr(Y* ptr) : _ptr(ptr), _count(1){}
294
295 /// default dtor
296 ~__SharedCountingPtr(){
297 // force the deletion of the object we keep track of
298 if (_ptr!=NULL){ delete _ptr;}
299 }
300
301 /// return a pointer to the object
302 inline T* get() const {return _ptr;}
303
304 /// return the count
305 inline long use_count() const {return _count;}
306
307 /// prefix increment operator
308 inline long operator++(){return ++_count;}
309
310 /// prefix decrement operator
311 inline long operator--(){return --_count;}
312
313 /// postfix increment operator
314 /// The "dummy" int argument is just a C++ trick to differentiate
315 /// it from the prefix increment
316 inline long operator++(int){return _count++;}
317
318 /// postfix decrement operator
319 /// The "dummy" int argument is just a C++ trick to differentiate
320 /// it from the prefix decrement
321 inline long operator--(int){return _count--;}
322
323 /// force the count to be set to a specified value
324 /// \param count the value that we ned to reset to
325 void set_count(const long & count){
326 _count = count;
327 }
328
329 private:
330 T *_ptr; ///< the pointer we're counting the references to
331 long _count; ///< the number of references
332 };
333
334private:
335 /// return the common container
336 inline __SharedCountingPtr* _get_container() const{
337 return _ptr;
338 }
339
340 /// decrease the pointer count and support deletion
341 /// Warning: we don't test that the pointer is allocated
342 /// This can be dangerous if we have explicitly reset the
343 /// count. Generally speaking, if the count goes negative
344 /// after _ptr has been effectively deleted, this is going
345 /// to lead to a segmentation fault. But, if in the course
346 /// of the deletion of _ptr, the deletion of its pointer
347 /// (_ptr::_ptr, i.e. the real data we're storing) makes
348 /// the counts to become negative, this is going to pass
349 /// smoothly.
350 void _decrease_count(){
351 // decrease the count
352 (*_ptr)--;
353
354 // if no one else is using it, free the allocated memory
355 if (_ptr->use_count()==0)
356 delete _ptr; // that automatically deletes the object itself
357 }
358
359 // the real info
360 __SharedCountingPtr *_ptr;
361};
362
363
364/// comparison: equality
365template<class T,class U>
366inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
367 return t.get() == u.get();
368}
369
370/// comparison: difference
371template<class T,class U>
372inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
373 return t.get() != u.get();
374}
375
376/// comparison: orgering
377template<class T,class U>
378inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){
379 return t.get() < u.get();
380}
381
382/// swapping
383template<class T>
384inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
385 return a.swap(b);
386}
387
388/// getting the pointer
389template<class T>
390inline T* get_pointer(SharedPtr<T> const & t){
391 return t.get();
392}
393
394#endif // __FASTJET_USETR1SHAREDPTR
395
396FASTJET_END_NAMESPACE // defined in fastjet/internal/base.hh
397
398#endif // __FASTJET_SHARED_PTR_HH__
Note: See TracBrowser for help on using the repository browser.