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