00001 #ifndef __FASTJET_SHARED_PTR_HH__ 00002 #define __FASTJET_SHARED_PTR_HH__ 00003 00004 //STARTHEADER 00005 // $Id: SharedPtr.hh 1761 2010-09-16 10:43:18Z soyez $ 00006 // 00007 // Copyright (c) 2005-2010, Matteo Cacciari, Gavin Salam and Gregory Soyez 00008 // 00009 //---------------------------------------------------------------------- 00010 // This file is part of FastJet. 00011 // 00012 // FastJet is free software; you can redistribute it and/or modify 00013 // it under the terms of the GNU General Public License as published by 00014 // the Free Software Foundation; either version 2 of the License, or 00015 // (at your option) any later version. 00016 // 00017 // The algorithms that underlie FastJet have required considerable 00018 // development and are described in hep-ph/0512210. If you use 00019 // FastJet as part of work towards a scientific publication, please 00020 // include a citation to the FastJet paper. 00021 // 00022 // FastJet is distributed in the hope that it will be useful, 00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 // GNU General Public License for more details. 00026 // 00027 // You should have received a copy of the GNU General Public License 00028 // along with FastJet; if not, write to the Free Software 00029 // Foundation, Inc.: 00030 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00031 //---------------------------------------------------------------------- 00032 //ENDHEADER 00033 00034 #include "fastjet/internal/base.hh" 00035 #include <cstdlib> // for NULL!!! 00036 00037 // for testing purposes, the following define makes it possible 00038 // for our SharedPtr simply to be derived from the STL TR1 one. 00039 // #define USETR1SHAREDPTR 00040 00041 #ifdef USETR1SHAREDPTR 00042 #include <tr1/memory> 00043 #endif // USETR1SHAREDPTR 00044 00045 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh 00046 00047 #ifdef USETR1SHAREDPTR 00048 00049 /// @ingroup advanced_usage 00050 /// \class SharedPtr 00051 /// replaces our shared pointer with the TR1 one (for testing purpose) 00052 /// 00053 /// for testing purposes, it can be useful to replace our home-made 00054 /// SharedPtr with the standard library one. Having a class derived 00055 /// from the standard one is way of arranging for this to happen. 00056 /// 00057 /// The other way of working this is a template class with an 00058 /// internal typedef (http://bytes.com/topic/c/answers/60312-typedef-template) 00059 /// since templated typedefs don't work in standard C++ 00060 template<class T> 00061 class SharedPtr : public std::tr1::shared_ptr<T> { 00062 public: 00063 SharedPtr() : std::tr1::shared_ptr<T>() {} 00064 SharedPtr(T * t) : std::tr1::shared_ptr<T>(t) {} 00065 SharedPtr(const SharedPtr<T> & t) : std::tr1::shared_ptr<T>(t) {} 00066 // for some reason operator() doesn't get inherited 00067 inline operator bool() const {return (this->get()!=NULL);} 00068 /// return the pointer we're pointing to 00069 T* operator ()() const{ 00070 return this->get(); // automatically returns NULL when out-of-scope 00071 } 00072 }; 00073 00074 00075 #else // USETR1SHAREDPTR 00076 00077 /** 00078 * @ingroup advanced_usage 00079 * \class SharedPtr 00080 * an implementation of C++0x shared pointers (or boost's) 00081 * 00082 * this class implements a smart pointer, based on the shared+ptr 00083 * proposal. A description of shared_ptr can be found in Section 2.2.3 00084 * of the first C++ Technical Report (TR1) 00085 * http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf 00086 * or, alternatively, on the Boost C++ library website at 00087 * http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm 00088 * 00089 * Our implementation is compatible with both of these apart from a 00090 * series of members and functions that have not been implemented: 00091 * - conversion from weak and auto pointers 00092 * - support for deleters and allocators 00093 * - static, constant and dynamic casts 00094 * - constructor and assignment sharing ownership with a shared 00095 * pointer r but storing a different pointer than r (needed for the 00096 * previous item) 00097 * In the last 2 cases, their implementation would require storing two 00098 * pointers for every copies of the shared pointer, while our 00099 * implementation only needs one. We did not implement then since we 00100 * want to limit as much as possible memory and time consumption, and 00101 * can easily avoid (at least for our needs so far) the casts. 00102 * 00103 * The class has been tested against the existing boost (v1.42) 00104 * implementation (for the parts that we have implemented). 00105 */ 00106 template<class T> 00107 class SharedPtr{ 00108 public: 00109 /// forward declaration of the counting container 00110 class __SharedCountingPtr; 00111 00112 /// default ctor 00113 SharedPtr() : _ptr(NULL){} 00114 00115 /// initialise with the main data 00116 /// \param t : the object we want a smart pointer to 00117 template<class Y> explicit SharedPtr(Y* ptr){ 00118 _ptr = new __SharedCountingPtr(ptr); 00119 } 00120 00121 /// overload the copy ctor so that it updates count 00122 /// \param share : the object we want to copy 00123 SharedPtr(SharedPtr const & share) : _ptr(NULL){ 00124 reset(share); 00125 } 00126 00127 /// overload the copy ctor so that it updates count 00128 /// \param share : the object we want to copy 00129 template<class Y> SharedPtr(SharedPtr<Y> const & share) : _ptr(NULL){ 00130 reset(share); 00131 } 00132 00133 /// default dtor 00134 ~SharedPtr(){ 00135 // make sure the object has been allocated 00136 if (_ptr==NULL) return; 00137 00138 _decrease_count(); 00139 } 00140 00141 /// reset the pointer to default value (NULL) 00142 void reset(){ 00143 // // if we already are pointing to sth, be sure to decrease its count 00144 // if (_ptr!=NULL) _decrease_count(); 00145 // _ptr = NULL; 00146 SharedPtr().swap(*this); 00147 } 00148 00149 /// reset from a pointer 00150 template<class Y> void reset(Y * ptr){ 00151 // // if we already are pointing to sth, be sure to decrease its count 00152 // if (_ptr!=NULL) _decrease_count(); 00153 // 00154 // _ptr = new __SharedCountingPtr(ptr); 00155 SharedPtr(ptr).swap(*this); 00156 } 00157 00158 // not part of the standard 00159 /// do a smart copy 00160 /// \param share : the object we want to copy 00161 /// Q? Do we need a non-template<Y> version as for the ctor and the assignment? 00162 template<class Y> void reset(SharedPtr<Y> const & share){ 00163 // if we already are pointing to sth, be sure to decrease its count 00164 if (_ptr!=NULL){ 00165 // in the specific case where we're having the same 00166 // share,reset() has actually no effect. However if *this is the 00167 // only instance still alive (implying share==*this) bringing 00168 // the count down to 0 and deleting the object will not have the 00169 // expected effect. So we just avoid that situation explicitly 00170 if (_ptr == share._get_container()) return; 00171 00172 _decrease_count(); 00173 } 00174 00175 // Watch out: if share is empty, construct an empty shared_ptr 00176 00177 // copy the container 00178 _ptr = share._get_container(); // Note: automatically set it to NULL if share is empty 00179 00180 if (_ptr!=NULL) 00181 (*_ptr)++; 00182 } 00183 00184 /// overload the = operator so that it updates count 00185 /// \param share : the object we want to copy 00186 SharedPtr& operator=(SharedPtr const & share){ 00187 reset(share); 00188 return *this; 00189 } 00190 00191 /// overload the = operator so that it updates count 00192 /// \param share : the object we want to copy 00193 template<class Y> SharedPtr& operator=(SharedPtr<Y> const & share){ 00194 reset(share); 00195 return *this; 00196 } 00197 00198 /// return the pointer we're pointing to 00199 T* operator ()() const{ 00200 if (_ptr==NULL) return NULL; 00201 return _ptr->get(); // automatically returns NULL when out-of-scope 00202 } 00203 00204 /// indirection, get a reference to the stored pointer 00205 /// 00206 /// !!! WATCH OUT 00207 /// It fails the requirement that the stored pointer must no be NULL!! 00208 /// So you need explicitly to check the validity in your code 00209 inline T& operator*() const{ 00210 return *(_ptr->get()); 00211 } 00212 00213 /// indirection, get the stored pointer 00214 /// 00215 /// !!! WATCH OUT 00216 /// It fails the requirement that the stored pointer must no be NULL!! 00217 /// So you need explicitly to check the validity in your code 00218 inline T* operator->() const{ 00219 if (_ptr==NULL) return NULL; 00220 return _ptr->get(); 00221 } 00222 00223 /// get the stored pointer 00224 inline T* get() const{ 00225 if (_ptr==NULL) return NULL; 00226 return _ptr->get(); 00227 } 00228 00229 /// check if the instance is unique 00230 inline bool unique() const{ 00231 return (use_count()==1); 00232 } 00233 00234 /// return the number of counts 00235 inline long use_count() const{ 00236 if (_ptr==NULL) return 0; 00237 return _ptr->use_count(); // automatically returns NULL when out-of-scope 00238 } 00239 00240 /// conversion to bool 00241 /// This will allow you to use the indirection nicely 00242 inline operator bool() const{ 00243 return (get()!=NULL); 00244 } 00245 00246 /// exchange the content of the two pointers 00247 inline void swap(SharedPtr & share){ 00248 __SharedCountingPtr* share_container = share._ptr; 00249 share._ptr = _ptr; 00250 _ptr = share_container; 00251 } 00252 00253 /** 00254 * \if internal_doc 00255 * \class __SharedCountingPtr 00256 * A reference-counting pointer 00257 * 00258 * This is implemented as a container for that pointer together with 00259 * reference counting. 00260 * The pointer is deleted when the number of counts goes to 0; 00261 * \endif 00262 */ 00263 class __SharedCountingPtr{ 00264 public: 00265 /// default ctor 00266 __SharedCountingPtr() : _ptr(NULL), _count(0){} 00267 00268 /// ctor with initialisation 00269 template<class Y> explicit __SharedCountingPtr(Y* ptr) : _ptr(ptr), _count(1){} 00270 00271 /// default dtor 00272 ~__SharedCountingPtr(){ 00273 // force the deletion of the object we keep track of 00274 if (_ptr!=NULL){ delete _ptr;} 00275 } 00276 00277 /// return a pointer to the object 00278 inline T* get() const {return _ptr;} 00279 00280 /// return the count 00281 inline long use_count() const {return _count;} 00282 00283 /// postfix incrementation 00284 inline long operator++(int unused){return _count++;} 00285 00286 /// postfix decrementation 00287 inline long operator--(int unused){return _count--;} 00288 00289 /// prefix incrementation 00290 inline long operator++(){return ++_count;} 00291 00292 /// prefix decrementation 00293 inline long operator--(){return --_count;} 00294 00295 private: 00296 T *_ptr; ///< the pointer we're counting the references to 00297 long _count; ///< the number of references 00298 }; 00299 00300 private: 00301 /// return the common container 00302 inline __SharedCountingPtr* _get_container() const{ 00303 return _ptr; 00304 } 00305 00306 /// decrease the pointer count and support deletion 00307 /// Warning: we don't test that the pointer is allocated 00308 void _decrease_count(){ 00309 // decrease the count 00310 (*_ptr)--; 00311 00312 // if no one else is using it, free the allocated memory 00313 if (_ptr->use_count()==0) 00314 delete _ptr; // that automatically deletes the object itself 00315 } 00316 00317 // the real info 00318 __SharedCountingPtr *_ptr; 00319 }; 00320 00321 00322 /// comparison: equality 00323 template<class T,class U> 00324 inline bool operator==(SharedPtr<T> const & t, SharedPtr<U> const & u){ 00325 return t.get() == u.get(); 00326 } 00327 00328 /// comparison: difference 00329 template<class T,class U> 00330 inline bool operator!=(SharedPtr<T> const & t, SharedPtr<U> const & u){ 00331 return t.get() != u.get(); 00332 } 00333 00334 /// comparison: orgering 00335 template<class T,class U> 00336 inline bool operator<(SharedPtr<T> const & t, SharedPtr<U> const & u){ 00337 return t.get() < u.get(); 00338 } 00339 00340 /// swapping 00341 template<class T> 00342 inline void swap(SharedPtr<T> & a, SharedPtr<T> & b){ 00343 return a.swap(b); 00344 } 00345 00346 /// getting the pointer 00347 template<class T> 00348 inline T* get_pointer(SharedPtr<T> const & t){ 00349 return t.get(); 00350 } 00351 00352 #endif // USETR1SHAREDPTR 00353 00354 FASTJET_END_NAMESPACE // defined in fastjet/internal/base.hh 00355 00356 #endif // __FASTJET_SHARED_PTR_HH__