casa
$Rev:20696$
|
00001 //# COWPtr.h: this defines the Copy-On-Write-Pointer class. 00002 //# Copyright (C) 1996,1997,1999 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 //# 00027 //# $Id: COWPtr.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $ 00028 00029 #ifndef CASA_COWPTR_H 00030 #define CASA_COWPTR_H 00031 00032 #include <casa/aips.h> 00033 #include <casa/Utilities/CountedPtr.h> 00034 00035 namespace casa { //# NAMESPACE CASA - BEGIN 00036 00037 // <summary> 00038 // Copy-On-Write-Pointer class - allows control of copy based on constness. 00039 // </summary> 00040 00041 // <use visibility=export> 00042 00043 // <reviewed reviewer="Ger van Diepen" date="1996/02/21" tests="tCOWPtr.cc" demos=""> 00044 // </reviewed> 00045 00046 // <prerequisite> 00047 // <li> none 00048 // </prerequisite> 00049 // 00050 // <etymology> 00051 // The COWPtr class name is a contraction of Copy-On-Write-Pointer 00052 // and is a reflection of its role as a carrier of objects which need to 00053 // minimize their copying and control their destruction. Such objects only 00054 // need to copy if written to. 00055 // </etymology> 00056 // 00057 // <synopsis> 00058 // COWPtr can be used by other classes to implement copy-on-write 00059 // semantics. Copy-on-write means that a copy of an object is not 00060 // made until necessary. A well-known example is a String class 00061 // with internally a pointer to a StringRep containing the true string. 00062 // When a copy of a String is made, the StringRep is not copied yet. 00063 // Only when the String gets changed and when more than one String 00064 // points to the same StringRep, a copy of the StringRep is made. 00065 // This technique can prevent a lot of copying when arguments are 00066 // passed by value. 00067 //<br> 00068 // Implementing a String in this way is straightforward when 00069 // String defines the pointer to its StringRep as <src>COWPtr<StringRep></src> 00070 // and uses the appropriate functions (ref() and rwRef()) to execute 00071 // const and non-const StringRep functions. 00072 //<br> 00073 // An example of this (straightforward) usage is class 00074 // <linkto class=RecordDesc>RecordDesc</linkto>. 00075 //<p> 00076 // COWPtr offers possibilities for more advanced usage: 00077 // <ul> 00078 // <li> Normally a copy (on write) is made when more than one String points to 00079 // the same StringRep. By constructing the COWPtr object with 00080 // readOnly=True, it is possible to already do that when only one 00081 // String points to a StringRep. This can be used when a function 00082 // returns an object referencing a constant object. For instance, 00083 // a function can return an Array object referencing another Array 00084 // which should not be altered. 00085 // By returning a <src>COWPtr<Array></src> with readOnly=True, 00086 // it is assured that a copy is made as soon as somebody wants 00087 // to change the returned Array object. No (expensive) copy is 00088 // made when only const access is being done. 00089 // <li> Normally the COWPtr object takes over the pointer and deletes 00090 // the underlying object when it is not used anymore. With the 00091 // deleteIt flag it is possible to change this behavior. 00092 //</ul> 00093 //<p> 00094 // Apart from the fact that COWPtr handles the copying, it has 00095 // the big advantage that it forces that its access functions (ref and 00096 // rwRef) are used in the correct way (ie. ref() for a const 00097 // function and rwRef() for a non-const function). This ensures that 00098 // copies are made when needed and not made when not needed. 00099 //<p> 00100 // Note that COWPtr uses the default constructor and the assignment 00101 // operator to make a copy (thus not the copy constructor). The 00102 // reason for this is that the copy constructor of some classes 00103 // (e.g. Array) has reference semantics iso. copy semantics. 00104 // </synopsis> 00105 // 00106 // <example> 00107 // <h4>Example 1:</h4> 00108 // <srcblock> 00109 // class String { 00110 // public: 00111 // // The constructor allocates a StringRep and hands to pointer 00112 // // to COWPtr. 00113 // String() 00114 // : itsRep (new StringRep;) {} 00115 // // This non-const function needs rwRef to make a copy when needed. 00116 // void set (const char* str) {itsRep.rwRef().set (str);} 00117 // // This const function can use ref (making a copy is not needed). 00118 // const char* get const {return itsRep.ref();} 00119 // private: 00120 // COWPtr<StringRep> itsRep; 00121 // }; 00122 // class StringRep { 00123 // friend class String; 00124 // private: 00125 // void set (const char*); 00126 // const char* get() const; 00127 // char* itsData; 00128 // }; 00129 //</srcblock> 00130 // <h4>Example 2:</h4> 00131 // This function requires a const Array be passed out from the local scope. 00132 // The Array is created with non-const functions out of necessity (i.e. no 00133 // const versions of the Array::getSlice() function exist.) Preventing 00134 // copies of the Array from being made forces us to use a COWPtr. The COWPtr 00135 // has arguments which allow us to declare the Array as const and not make 00136 // any copies until a write operation is performed. 00137 // <srcblock> 00138 // void myFunc(COWPtr<Array<Float> > &obj){ 00139 // // make a nonconst from some static const Array that exists "out there" 00140 // Array<Float> &nonConstArray = (Array<Float> &)staticConstArray; 00141 // // "fill" the COWPtr and bring back constness without copying. The first 00142 // // "True" argument indicates the caller of this function may take 00143 // // control of the dynamic pointer's destruction. The second "True" 00144 // // argument indicates the array is read only and should make a copy of 00145 // // itself if writing is needed. 00146 // obj.set(new Array<Float>(nonConstArray.getSlice(...), True, True)); 00147 // } 00148 // </srcblock> 00149 // The caller of the function will get their piece of a const array without 00150 // making a copy until the last possible moment (maybe never.) 00151 // <srcblock> 00152 // #include <casa/Utilities/COWPtr.h> 00153 // main(){ 00154 // // create a null filled COWPtr 00155 // COWPtr<Array<Float> > COW; 00156 // // fill it inside myfunc 00157 // myFunc(COW); 00158 // // use a single element - still no copies have been made! 00159 // Float someVal = COW->operator()(IPosition(2,3,3)) 00160 // // write to the array - now we get a copy! 00161 // COW.rwRef().set(42.0f); 00162 // // etc... 00163 // }; 00164 // </srcblock> 00165 // </example> 00166 // 00167 // <motivation> 00168 // Three words; efficiency, efficiency, efficiency. Not everything may be 00169 // passed as a reference. With COWPtrs we may fake it. 00170 // </motivation> 00171 // 00172 // <templating arg=T> 00173 // <li> default constructor 00174 // <li> assignment operator 00175 // </templating> 00176 // 00177 // <thrown> 00178 // <li> AipsError 00179 // </thrown> 00180 // 00181 // <todo asof="1996/01/16"> 00182 // <li> none 00183 // </todo> 00184 00185 template <class T> class COWPtr 00186 { 00187 public: 00188 00189 // The default constructor: used to create a null pointer which is 00190 // delete-able by the destructor. It is not "readOnly" so that it may be 00191 // changed by the COWPtr<T>::set() function. 00192 inline COWPtr(); 00193 00194 // The dynamic "pointer to object" constructor: default behavior is to 00195 // delete the allocated memory when this instance's of COWPtr is destructed. 00196 // Or the Boolean argument of "deleteIt = False" implies the pointer is 00197 // being maintained by an object other than this instance of COWPtr and 00198 // will not delete the allocated memory upon this instance's destruction. 00199 // Control of copying is provided by the Boolean "readOnly" argument. The 00200 // default value of "readOnly = False" forces a copy if the number of 00201 // references to the dynamic memory is greater than one. Copying is always 00202 // done if the constructor is given an argument of "readOnly = True". 00203 // <note> The only copying done (if ever) is upon a call to 00204 // COWPtr<T>::rwRef().</note> 00205 explicit COWPtr(T *obj, Bool deleteIt = True, Bool readOnly = False); 00206 00207 // copy ctor with reference semantics 00208 inline COWPtr(const COWPtr<T> &other); 00209 00210 // assignment operator with reference semantics 00211 inline COWPtr &operator=(const COWPtr<T> &other); 00212 00213 // return a pointer to a const object. This prevents "write" operations. 00214 inline const T *operator->() const; 00215 00216 // return a reference to a const object. This prevents "write" operations. 00217 inline const T &operator*() const; 00218 00219 // Function used to change this instance of COWPtr. The pointer must be 00220 // dynamically allocated. Default behavior is to 00221 // delete the allocated memory when this instance's of COWPtr is destructed. 00222 // Or the Boolean argument of "deleteIt = False" implies the pointer is 00223 // being maintained by an object other than this instance of COWPtr and 00224 // will not delete the allocated memory upon this instance's destruction. 00225 // Control of copying is provided by the Boolean "readOnly" argument. The 00226 // default value of "readOnly = False" forces a copy if the number of 00227 // references to the dynamic memory is greater than one. Copying is always 00228 // done if the constructor is given an argument of "readOnly = True". 00229 // <note> The only copying done (if ever) is upon a call to 00230 // COWPtr<T>::rwRef(). 00231 // </note> 00232 // The <src>setReadOnly</src> function is the same as <src>set</src>, but 00233 // forces <src>deleteIt=False</src> and <src>ReadOnly=True</src>. In 00234 // that way a const object can also be safely referenced by COWPtr. 00235 // <group> 00236 void set(T *obj, Bool deleteIt = True, Bool readOnly = False); 00237 void setReadOnly (const T *obj); 00238 void setReadOnly (); 00239 // </group> 00240 00241 // return a const reference to the object. 00242 inline const T &ref() const; 00243 00244 // return a readable and writable reference to this instance. Instances of 00245 // COWPtr constructed with argument "readOnly = True" will be made a copy. 00246 // Additionally, all instances of COWPtr with more than one reference to 00247 // the allocated memory stored within will be copied. 00248 inline T &rwRef(); 00249 00250 // returns False if this contains a non-null ptr, otherwise, return True. 00251 inline Bool isNull() const; 00252 00253 // returns True if the object is const, otherwise, return False. 00254 inline Bool isReadOnly() const; 00255 00256 // returns True if the object is the only instance, otherwise, return False. 00257 inline Bool isUnique() const; 00258 00259 // Return True if copied, otherwise, False. This function will make this 00260 // instance's object a copy if it is constructed with 00261 // "readOnly = True." Additionally, all instances of COWPtr with more 00262 // than one reference to the allocated memory stored within will be 00263 // copied. 00264 Bool makeUnique(); 00265 00266 protected: 00267 CountedPtr<T> obj_p; 00268 Bool const_p; 00269 }; 00270 00271 00272 00273 // Make our own default pointer - deleteIt==True by default, const_p==False 00274 template <class T> inline COWPtr<T>::COWPtr() 00275 :obj_p(static_cast<T *>(0), True), const_p(False) 00276 { 00277 // does nothing 00278 } 00279 00280 // copy ctor with reference semantics 00281 template <class T> inline COWPtr<T>::COWPtr(const COWPtr<T> &other) 00282 : obj_p(other.obj_p), const_p(other.const_p) 00283 { 00284 // does nothing 00285 } 00286 00287 //assignment operator with reference semantics 00288 template <class T> 00289 inline COWPtr<T> &COWPtr<T>::operator=(const COWPtr<T> &other) 00290 { 00291 if (this != &other){ 00292 obj_p = other.obj_p; 00293 const_p = other.const_p; 00294 } 00295 return *this; 00296 } 00297 00298 template <class T> inline void COWPtr<T>::setReadOnly (const T *obj) 00299 { 00300 set ((T*)obj, False, True); 00301 } 00302 00303 template <class T> inline void COWPtr<T>::setReadOnly () 00304 { 00305 const_p = True; 00306 } 00307 00308 template <class T> inline const T *COWPtr<T>::operator->() const 00309 { 00310 return obj_p.operator->(); 00311 } 00312 00313 template <class T> inline const T &COWPtr<T>::operator*() const 00314 { 00315 return obj_p.operator*(); 00316 } 00317 00318 template <class T> inline const T &COWPtr<T>::ref() const 00319 { 00320 return *obj_p; 00321 } 00322 00323 template <class T> inline T &COWPtr<T>::rwRef() 00324 { 00325 makeUnique(); 00326 return *obj_p; 00327 } 00328 00329 template <class T> inline Bool COWPtr<T>::isNull() const 00330 { 00331 return obj_p.null(); 00332 } 00333 00334 template <class T> inline Bool COWPtr<T>::isReadOnly() const 00335 { 00336 return const_p; 00337 } 00338 00339 template <class T> inline Bool COWPtr<T>::isUnique() const 00340 { 00341 return (const_p || obj_p.nrefs()>1) ? False : True; 00342 } 00343 00344 00345 00346 } //# NAMESPACE CASA - END 00347 00348 #ifndef CASACORE_NO_AUTO_TEMPLATES 00349 #include <casa/Utilities/COWPtr.tcc> 00350 #endif //# CASACORE_NO_AUTO_TEMPLATES 00351 #endif