FastJet  3.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
SharedPtr.hh
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 
45 FASTJET_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).
67 template<class T>
68 class SharedPtr : public std::tr1::shared_ptr<T> {
69 public:
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  */
115 template<class T>
116 class SharedPtr{
117 public:
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
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 
334 private:
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
365 template<class T,class U>
366 inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
367  return t.get() == u.get();
368 }
369 
370 /// comparison: difference
371 template<class T,class U>
372 inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
373  return t.get() != u.get();
374 }
375 
376 /// comparison: orgering
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 /// swapping
383 template<class T>
384 inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
385  return a.swap(b);
386 }
387 
388 /// getting the pointer
389 template<class T>
390 inline T* get_pointer(SharedPtr<T> const & t){
391  return t.get();
392 }
393 
394 #endif // __FASTJET_USETR1SHAREDPTR
395 
396 FASTJET_END_NAMESPACE // defined in fastjet/internal/base.hh
397 
398 #endif // __FASTJET_SHARED_PTR_HH__
T * get_pointer(SharedPtr< T > const &t)
getting the pointer
Definition: SharedPtr.hh:390
long use_count() const
return the number of counts
Definition: SharedPtr.hh:252
SharedPtr()
default ctor
Definition: SharedPtr.hh:122
SharedPtr & operator=(SharedPtr< Y > const &share)
overload the = operator so that it updates count
Definition: SharedPtr.hh:208
SharedPtr(SharedPtr const &share)
overload the copy ctor so that it updates count
Definition: SharedPtr.hh:132
void reset(Y *ptr)
reset from a pointer
Definition: SharedPtr.hh:165
void reset(SharedPtr< Y > const &share)
do a smart copy
Definition: SharedPtr.hh:177
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:251
T & operator*() const
indirection, get a reference to the stored pointer
Definition: SharedPtr.hh:225
~SharedPtr()
default dtor
Definition: SharedPtr.hh:148
void swap(SharedPtr &share)
exchange the content of the two pointers
Definition: SharedPtr.hh:264
SharedPtr(Y *ptr)
initialise with the main data
Definition: SharedPtr.hh:126
an implementation of C++0x shared pointers (or boost's)
Definition: SharedPtr.hh:116
bool operator!=(const PseudoJet &a, const PseudoJet &b)
inequality test which is exact opposite of operator==
Definition: PseudoJet.hh:831
void swap(SharedPtr< T > &a, SharedPtr< T > &b)
swapping
Definition: SharedPtr.hh:384
T * operator->() const
indirection, get the stored pointer
Definition: SharedPtr.hh:235
SharedPtr & operator=(SharedPtr const &share)
overload the = operator so that it updates count
Definition: SharedPtr.hh:201
bool unique() const
check if the instance is unique
Definition: SharedPtr.hh:247
T * get() const
get the stored pointer
Definition: SharedPtr.hh:241
void set_count(const long &count)
force the count to be set to a specified value
Definition: SharedPtr.hh:272
void reset()
reset the pointer to default value (NULL)
Definition: SharedPtr.hh:156