casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
COWPtr.h
Go to the documentation of this file.
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