Fork me on GitHub

source: svn/trunk/external/fastjet/SharedPtr.hh@ 1330

Last change on this file since 1330 was 859, checked in by Pavel Demin, 12 years ago

update fastjet to version 3.0.3

File size: 12.7 KB
Line 
1#ifndef __FASTJET_SHARED_PTR_HH__
2#define __FASTJET_SHARED_PTR_HH__
3
4//STARTHEADER
5// $Id: SharedPtr.hh 2680 2011-11-12 17:12:05Z soyez $
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 USETR1SHAREDPTR
38
39#ifdef USETR1SHAREDPTR
40#include <tr1/memory>
41#endif // USETR1SHAREDPTR
42
43FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
44
45#ifdef 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).
65template<class T>
66class SharedPtr : public std::tr1::shared_ptr<T> {
67public:
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 // 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 */
113template<class T>
114class SharedPtr{
115public:
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
146 ~SharedPtr(){
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
332private:
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
363template<class T,class U>
364inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){
365 return t.get() == u.get();
366}
367
368/// comparison: difference
369template<class T,class U>
370inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){
371 return t.get() != u.get();
372}
373
374/// comparison: orgering
375template<class T,class U>
376inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){
377 return t.get() < u.get();
378}
379
380/// swapping
381template<class T>
382inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){
383 return a.swap(b);
384}
385
386/// getting the pointer
387template<class T>
388inline T* get_pointer(SharedPtr<T> const & t){
389 return t.get();
390}
391
392#endif // USETR1SHAREDPTR
393
394FASTJET_END_NAMESPACE // defined in fastjet/internal/base.hh
395
396#endif // __FASTJET_SHARED_PTR_HH__
Note: See TracBrowser for help on using the repository browser.