00001 //# CountedPtr.h: Referenced counted pointer classes 00002 //# Copyright (C) 1993,1994,1995,1996,1999,2001 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef CASA_COUNTEDPTR_H 00029 #define CASA_COUNTEDPTR_H 00030 00031 #include <casacore/casa/aips.h> 00032 00033 #if (defined(AIPS_CXX11) || (defined(__APPLE_CC__) && __APPLE_CC__ > 5621)) 00034 #include <memory> 00035 #define SHARED_PTR std::shared_ptr 00036 #define DYNAMIC_POINTER_CAST std::dynamic_pointer_cast 00037 #define CONST_POINTER_CAST std::const_pointer_cast 00038 #define STATIC_POINTER_CAST std::static_pointer_cast 00039 #else 00040 #include <tr1/memory> 00041 #define SHARED_PTR std::tr1::shared_ptr 00042 #define DYNAMIC_POINTER_CAST std::tr1::dynamic_pointer_cast 00043 #define CONST_POINTER_CAST std::tr1::const_pointer_cast 00044 #define STATIC_POINTER_CAST std::tr1::static_pointer_cast 00045 #endif 00046 00047 namespace casacore { //#Begin casa namespace 00048 00049 00050 // <summary> act on dereference error </summary> 00051 // <synopsis> 00052 // Global function that throws an exception. It is called by the 00053 // member functions of the counted pointer classes when an 00054 // un-initialized (null) pointer is followed. 00055 // </synopsis> 00056 // <group name=dereference_error> 00057 void throw_Null_CountedPtr_dereference_error(); 00058 // </group> 00059 00060 00061 // <summary>Referenced counted pointer for constant data</summary> 00062 // <use visibility=export> 00063 // <reviewed reviewer="Friso Olnon" date="1995/03/15" tests="tCountedPtr" demos=""> 00064 00065 // <etymology> 00066 // This class is <em>Counted</em> because it is reference counted. 00067 // </etymology> 00068 00069 // <synopsis> 00070 // This class implements a reference counting mechanism. It 00071 // allows <src>CountedPtr</src>s to be passed around freely, 00072 // incrementing or decrementing the reference count as needed when one 00073 // <src>CountedPtr</src> is assigned to another. When the 00074 // reference count reaches zero the internal storage is deleted by 00075 // default, but this behavior can be overridden. 00076 // 00077 // Internally the class uses std::shared_ptr to be thread-safe. Note that 00078 // tr1 is used if the compiler does not support C++11 yet. 00079 // </synopsis> 00080 00081 // <motivation> 00082 // Reference counting 00083 // </motivation> 00084 00085 template<class t> 00086 class CountedPtr 00087 { 00088 00089 protected: 00090 // Helper class to make deletion of object optional. 00091 template <typename T> 00092 class Deleter { 00093 public: 00094 Deleter (Bool deleteIt) : reallyDeleteIt_p (deleteIt) {} 00095 void operator() (T * data) const { if (reallyDeleteIt_p) delete data;} 00096 private: 00097 Bool reallyDeleteIt_p; 00098 }; 00099 00100 00101 public: 00102 00103 00104 00105 // This constructor allows for the creation of a null 00106 // <src>CountedPtr</src>. The assignment operator can be used 00107 // to assign a null <src>CountedPtr</src> from another 00108 // pointer. 00109 // 00110 CountedPtr() : pointerRep_p () {} 00111 00112 // This constructor sets up a reference count for the <src>val</src> 00113 // pointer. By default, the data pointed to by <src>val</src> 00114 // will be deleted when it is no longer referenced. Passing in 00115 // <src>False</src> for <src>delit</src> will prevent the data 00116 // from being deleted when the reference count reaches zero. 00117 // 00118 // <note role=warning> After the counted pointer is initialized 00119 // the value should no longer be manipulated by the raw pointer of 00120 // type <src>t*</src>. 00121 // </note> 00122 CountedPtr(t *val, Bool delit = True) 00123 : pointerRep_p (val, Deleter<t> (delit)) 00124 {} 00125 00126 // This copy constructor allows <src>CountedPtr</src>s to be 00127 // initialized from other <src>CountedPtr</src>s for which the pointer TP* 00128 // is convertible to T*. 00129 template<typename TP> 00130 CountedPtr(const CountedPtr<TP>& that) 00131 : pointerRep_p(that.pointerRep_p) 00132 {} 00133 00134 // Create from a shared_ptr. 00135 CountedPtr (const SHARED_PTR<t>& rep) 00136 : pointerRep_p (rep) 00137 {} 00138 00139 // This destructor only deletes the really stored data when it was 00140 // initialized as deletable and the reference count is zero. 00141 ~CountedPtr() {} 00142 00143 // This assignment operator allows <src>CountedPtr</src>s to be 00144 // copied from other <src>CountedPtr</src>s for which the pointer TP* 00145 // is convertible to t*. 00146 template<typename TP> 00147 CountedPtr<t>& operator=(const CountedPtr<TP>& that) 00148 { 00149 pointerRep_p = that.pointerRep_p; 00150 return *this; 00151 } 00152 00153 // Reset the pointer. 00154 // <group> 00155 void reset (t *val, Bool delit=True) 00156 { pointerRep_p = PointerRep (val, Deleter<t>(delit)); } 00157 void reset() 00158 { pointerRep_p.reset(); } 00159 // </group> 00160 00161 // The <src>CountedPtr</src> indirection operator simply 00162 // returns a reference to the value being protected. If the pointer 00163 // is un-initialized (null), an exception will be thrown. The member 00164 // function 00165 // <linkto class="CountedPtr:null()const">null</linkto>() 00166 // can be used to catch such a condition in time. 00167 // <note role=tip> The address of the reference returned should 00168 // not be stored for later use. 00169 // </note> 00170 t &operator*() const { 00171 if (null()){ 00172 throw_Null_CountedPtr_dereference_error(); 00173 } 00174 return pointerRep_p.operator* (); 00175 } 00176 00177 // This dereferencing operator behaves as expected; it returns the 00178 // pointer to the value being protected, and then its dereferencing 00179 // operator will be invoked as appropriate. If the pointer is 00180 // un-initialized (null), an exception will be thrown. The member 00181 // function 00182 // <linkto class="CountedPtr:null()const">null</linkto>() 00183 // can be used to catch such a condition in time. 00184 t *operator->() const { 00185 return get (); 00186 } 00187 00188 // Get the underlying pointer. 00189 t* get () const { 00190 return pointerRep_p.get(); 00191 } 00192 00193 // Equality operator which checks to see if two 00194 // <src>CountedPtr</src>s are pointing at the same thing. 00195 Bool operator==(const CountedPtr<t> &other) const { 00196 return (get() == other.get()); 00197 } 00198 //# Note: use of const void* gives ambiguius overload error. 00199 Bool operator==(int ptr) const { 00200 return (ptr == 0 && get() == 0); 00201 } 00202 00203 // Non-equality operator which checks to see if two 00204 // <src>CountedPtr</src>s are not pointing at the same thing. 00205 Bool operator!=(const CountedPtr<t> &other) const { 00206 return (get() != other.get() ? True : False); 00207 } 00208 //# Note: use of const void* gives ambiguius overload error. 00209 Bool operator!=(int ptr) const { 00210 return (ptr != 0 || get() != 0); 00211 } 00212 00213 // This assignment operator allows the object to which the current 00214 // <src>CountedPtr</src> points to be changed. 00215 CountedPtr<t> & 00216 operator=(t *v) 00217 { 00218 pointerRep_p = PointerRep (v); 00219 return * this; 00220 } 00221 00222 // Cast functions. 00223 // <group> 00224 template<typename U> 00225 CountedPtr<U> static_ptr_cast() const 00226 { return CountedPtr<U> (STATIC_POINTER_CAST<U> (pointerRep_p)); } 00227 template<typename U> 00228 CountedPtr<U> const_ptr_cast() const 00229 { return CountedPtr<U> (CONST_POINTER_CAST<U> (pointerRep_p)); } 00230 template<typename U> 00231 CountedPtr<U> dynamic_ptr_cast() const 00232 { return CountedPtr<U> (DYNAMIC_POINTER_CAST<U> (pointerRep_p)); } 00233 // </group> 00234 00235 // Sometimes it is useful to know if there is more than one 00236 // reference made. This is a way of getting that. Of course the point 00237 // of these classes is that this information is normally not required. 00238 uInt nrefs() const 00239 { return pointerRep_p.use_count(); } 00240 00241 // Check to see if this <src>CountedPtr</src> is 00242 // un-initialized, null. 00243 Bool null() const 00244 { return get() == 0; } 00245 00246 // Test if it contains a valid pointer. 00247 operator bool() const 00248 { return get() != 0; } 00249 00250 private: 00251 // Make all types of CountedPtr a friend for the templated operator=. 00252 template<typename TP> friend class CountedPtr; 00253 00254 typedef SHARED_PTR<t> PointerRep; 00255 00256 PointerRep pointerRep_p; 00257 }; 00258 00259 // A shared_ptr is used as implementation. 00260 inline Bool countedPtrShared() 00261 { return True; } 00262 00263 // Cast the CountedPtr from one pointer type to another. 00264 template<typename T, typename U> 00265 CountedPtr<T> static_pointer_cast (const CountedPtr<U>& that) 00266 { return that.template static_ptr_cast<T>(); } 00267 template<typename T, typename U> 00268 CountedPtr<T> const_pointer_cast (const CountedPtr<U>& that) 00269 { return that.template const_ptr_cast<T>(); } 00270 template<typename T, typename U> 00271 CountedPtr<T> dynamic_pointer_cast (const CountedPtr<U>& that) 00272 { return that.template dynamic_ptr_cast<T>(); } 00273 00274 00275 } //#End casa namespace 00276 00277 00278 #ifndef CASACORE_NO_AUTO_TEMPLATES 00279 #include <casacore/casa/Utilities/CountedPtr.tcc> 00280 #endif //# CASACORE_NO_AUTO_TEMPLATES 00281 00282 #endif