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