casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
PtrHolder.h
Go to the documentation of this file.
00001 //# PtrHolder.h: Hold and delete pointers not deleted by object destructors
00002 //# Copyright (C) 1994,1995,1999,2000
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: PtrHolder.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $
00027 
00028 #ifndef CASA_PTRHOLDER_H
00029 #define CASA_PTRHOLDER_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 
00034 
00035 namespace casa { //# NAMESPACE CASA - BEGIN
00036 
00037 // <summary>
00038 // Hold and delete pointers not deleted by object destructors
00039 // </summary>
00040 
00041 // <use visibility=export>
00042 // <reviewed reviewer="troberts" date="1995/07/29" tests="tPtrHolder">
00043 // </reviewed>
00044 
00045 // <prerequisite>
00046 //   <li> module <linkto module=Exceptions>Exceptions</linkto>
00047 // </prerequisite>
00048 
00049 // <synopsis> 
00050 // <src>PtrHolder</src>s hold allocated pointers which should be
00051 // deleted when an exception is thrown. Exceptions only call destructors
00052 // of objects. Thus, for example, storage allocated in a global function
00053 // (outside of an object)is not deleted. A <src>PtrHolder</src> solves
00054 // this problem: it merely holds the pointer and deletes it when it is
00055 // destroyed itself, e.g. when an exception is thrown or when the
00056 // function exits normally.
00057 // </synopsis> 
00058 
00059 // <example>
00060 // <srcblock>
00061 //    void func(Int *ptr); // some other function that takes a pointer
00062 //    // ...
00063 //    // True below means it's an array, False (the default) would mean
00064 //    // a singleton object.
00065 //    PtrHolder<Int> iholder(new Int[10000], True);
00066 //    func(iholder);                           // converts automatically to ptr
00067 //    (iholder.ptr() + 5) = 11;                // use pointer explicitly
00068 //    some_function_that_throws_exception();   // pointer is deleted
00069 // </srcblock>
00070 // </example>
00071 
00072 // <motivation>
00073 // Avoid leaks when throwing/catching exceptions.
00074 // </motivation>
00075 
00076 // <todo asof="2000/04/11">
00077 //   <li> Use the autoptr class from the Standard Library
00078 // </todo>
00079 
00080 
00081 template<class T> class PtrHolder
00082 {
00083 public:
00084     // The default constructor uses a null pointer.
00085     PtrHolder();
00086 
00087     // Construct a <src>PtrHolder</src> from a pointer which MUST have
00088     // been allocated from <src>new</src>, since the destructor will
00089     // call <src>delete</src> on it. If the pointer is to an array,
00090     // i.e. allocated with operator <src>new[]</src>, then
00091     // <src>isCarray</src> should be set to True. (This parameter is
00092     // required because C-arrays need to be deleted with
00093     // <src>delete[]</src>.)
00094     //
00095     // After the pointer is placed into the holder, the user should
00096     // not manually delete the pointer; the <src>PtrHolder</src>
00097     // object will do that, unless <src>set()</src> or
00098     // <src>clear()</src> is called with <src>deleteCurrentPtr</src>
00099     // set to False. The pointer must also only be put into
00100     // <em>one</em> holder to avoid double deletion.
00101     PtrHolder(T *pointer, Bool isCArray = False);
00102 
00103     ~PtrHolder();
00104 
00105     // Set the pointer to a new value. If <src>deleteCurrentPtr </src>is
00106     // True (the default), then delete the existing pointer first. If
00107     // <src>isCarray</src> is True, then the new pointer is assumed to
00108     // have been allocated with <src>new[]</src>.
00109     void set(T *pointer, Bool isCarray = False, Bool deleteCurrentPtr = True);
00110 
00111     // Set the current pointer to null; if <src>deletePtr</src> is True
00112     // (the default), then the current pointer is deleted first.
00113     void clear(Bool deleteCurrentPtr = True);
00114 
00115     // Release the pointer for use.
00116     // <group>
00117     T *ptr() { return ptr_p; }
00118     const T *ptr() const { return ptr_p; }
00119     // </group>
00120 
00121     // Attempt to automatically release a pointer when required. If the
00122     // compiler can't figure it out, you can use the <src>ptr()</src>
00123     // member function directly.
00124     // <group>
00125     operator T *() { return ptr_p; }
00126     operator const T *() const { return ptr_p; }
00127     // </group>
00128 
00129     // See if the pointer points to a C-array.
00130     Bool isCArray() const {return isCarray_p;}
00131 
00132 private:
00133     //# Undefined and inaccessible
00134     PtrHolder(const PtrHolder<T> &other);
00135     PtrHolder<T> &operator=(const PtrHolder<T> &other);
00136 
00137     //# We'd also like the following to be undefined and inaccessible, 
00138     //# unfortunately CFront doesn't seem to let you do that.
00139     //# void *operator new(size_t s);
00140 
00141     //# Put functionality in one place
00142     void delete_pointer_if_necessary();
00143 
00144     T *ptr_p;
00145     //# If space were critical, we could make isCarray_p a char
00146     Bool isCarray_p;
00147 };
00148 
00149 
00150 
00151 // <summary>
00152 // Hold and delete pointers not deleted by object destructors
00153 // </summary>
00154 
00155 // <use visibility=export>
00156 // <reviewed reviewer="" date="" tests="tPtrHolder">
00157 // </reviewed>
00158 
00159 // <prerequisite>
00160 //   <li> module <linkto module=Exceptions>Exceptions</linkto>
00161 // </prerequisite>
00162 
00163 // <synopsis> 
00164 // <src>SPtrHolder</src>s hold allocated pointers to non-array objects
00165 // which should be deleted when an exception is thrown.
00166 // SPtrHolder is similar to PtrHolder, but easier to use and only valid
00167 // for pointer to a single object, thus not to a C-array of objects.
00168 // </synopsis> 
00169 
00170 // <example>
00171 // <srcblock>
00172 //    void func(Table *ptr); // some other function that takes a pointer
00173 //    // ...
00174 //    // True below means it's an array, False (the default) would mean
00175 //    // a singleton object.
00176 //    SPtrHolder<Int> iholder(new Table(...));
00177 //    func(iholder);                           // converts automatically to ptr
00178 //    Table* tab = iholder.transfer();         // transfer ownership
00179 // </srcblock>
00180 // If an exception is thrown in function <src>func</src>, the Table will be
00181 // deleted automatically. After the function call, the ownership is tranfered
00182 // back to the 'user' 
00183 // </example>
00184 
00185 // <motivation>
00186 // <src>std::autoptr</src> is harder to use and its future is unclear.
00187 // <br>
00188 // <src>PtrHolder</src> is not fully inlined and has C-array overhead.
00189 // Furthermore the automatic conversion to a T* is dangerous, because the
00190 // programmer may not be aware that the pointer is maybe taken over.
00191 // </motivation>
00192 
00193 
00194 template<class T> class SPtrHolder
00195 {
00196 public:
00197   // Construct an <src>SPtrHolder</src> from a pointer which MUST have
00198   // been allocated from <src>new</src>, since the destructor will
00199   // After the pointer is placed into the holder, the user should
00200   // not manually delete the pointer unless the transfer function is called.
00201   // The pointer must also only be put into
00202   // <em>one</em> holder to avoid double deletion.
00203   explicit SPtrHolder (T* ptr = 0)
00204     : itsPtr(ptr) {}
00205 
00206   ~SPtrHolder()
00207     { delete itsPtr; }
00208 
00209   // Reset the pointer.
00210   void reset (T* ptr)
00211     { if (ptr != itsPtr) { delete itsPtr; itsPtr = ptr; }}
00212 
00213   // Transfer ownership of the pointer.
00214   // I.e. return the pointer and set it to 0 in the object.
00215   T* transfer()
00216     { T* ptr = itsPtr; itsPtr = 0; return ptr; }
00217 
00218   // Release the pointer.
00219   void release()
00220     { itsPtr = 0; }
00221 
00222   // Make it possible to dereference the pointer object.
00223   // <group>
00224   T& operator*()
00225     { return *itsPtr; }
00226   const T& operator*() const
00227     { return *itsPtr; }
00228   // </group>
00229 
00230   // Make it possible to use -> on the pointer object.
00231   // <group>
00232   T* operator->()
00233     { return itsPtr; }
00234   const T* operator->() const
00235     { return itsPtr; }
00236   // </group>
00237 
00238   // Get the pointer for use.
00239   // <group>
00240   T* ptr()
00241     { return itsPtr; }
00242   const T* ptr() const
00243     { return itsPtr; }
00244   // </group>
00245 
00246 private:
00247   // SPrtHolder cannot be copied.
00248   // <group>
00249   SPtrHolder(const SPtrHolder<T> &other);
00250   SPtrHolder<T> &operator=(const SPtrHolder<T> &other);
00251   // </group>
00252 
00253   //# The pointer itself.
00254   T* itsPtr;
00255 };
00256 
00257 
00258 
00259 } //# NAMESPACE CASA - END
00260 
00261 #ifndef CASACORE_NO_AUTO_TEMPLATES
00262 #include <casa/Utilities/PtrHolder.tcc>
00263 #endif //# CASACORE_NO_AUTO_TEMPLATES
00264 #endif