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 <casa/aips.h> 00032 00033 namespace casa { //#Begin casa namespace 00034 00035 //# Forward Declarations 00036 template<class t> class SimpleCountedPtr; 00037 template<class t> class SimpleCountedConstPtr; 00038 template<class t> class CountedPtr; 00039 template<class t> class CountedConstPtr; 00040 00041 // <summary> act on dereference error </summary> 00042 // <synopsis> 00043 // Global function that throws an exception. It is called by the 00044 // member functions of the counted pointer classes when an 00045 // un-initialized (null) pointer is followed. 00046 // </synopsis> 00047 // <group name=dereference_error> 00048 void throw_Null_CountedPtr_dereference_error(); 00049 // </group> 00050 00051 // <summary>Internal representation for <src>CountedPtr</src></summary> 00052 // <use visibility=local> 00053 // <reviewed reviewer="Friso Olnon" date="1995/03/15" tests="tCountedPtr" demos=""> 00054 00055 // <prerequisite> 00056 // <li> class <linkto class="SimpleCountedPtr:description">SimpleCountedPtr</linkto> 00057 // <li> class <linkto class="SimpleCountedConstPtr:description">SimpleCountedConstPtr</linkto> 00058 // </prerequisite> 00059 00060 // <synopsis> 00061 // This class is a utility class for 00062 // <linkto class="CountedConstPtr:description">CountedConstPtr</linkto> 00063 // and <linkto class="CountedPtr:description">CountedPtr</linkto>. 00064 // It stores the reference count and the pointer to the real data. 00065 // 00066 // <note role=tip> It is currently a template and is used such that 00067 // <src>t</src> is the <em>true</em> type of the stored pointer. This 00068 // means, however, that when it is used, a template instantiation must be 00069 // done for each type which <src>t</src> assumes. This makes debugging 00070 // easier, but in the future all of these pointers could be declared with 00071 // <src>void</src> type to avoid template instantiations. 00072 // </note> 00073 // </synopsis> 00074 00075 // <motivation> 00076 // This class isolates all of the low level management of the reference. 00077 // </motivation> 00078 00079 template<class t> class PtrRep 00080 { 00081 00082 public: 00083 00084 friend class SimpleCountedPtr<t>; 00085 friend class SimpleCountedConstPtr<t>; 00086 friend class CountedPtr<t>; 00087 friend class CountedConstPtr<t>; 00088 00089 protected: 00090 00091 // This constructor sets up the reference count to one and 00092 // initializes the pointer to the real data. The 00093 // <src>delit</src> flag can be passed in to indicate whether 00094 // the real data should be freed or not when the 00095 // reference count reaches zero. 00096 // <group> 00097 PtrRep(t *v) : val(v), count(1), deletable(True) {} 00098 PtrRep(t *v, Bool delit) : val(v), count(1), deletable(delit) {} 00099 // </group> 00100 00101 // This deletes the real data if indeed it can be deleted. 00102 void freeVal(); 00103 00104 // This destructor uses the <src>deletable</src> flag to indicate if the 00105 // real data should be freed or not. 00106 // 00107 ~PtrRep() { 00108 freeVal(); 00109 } 00110 00111 private: 00112 00113 t *val; 00114 unsigned int count; 00115 Bool deletable; 00116 00117 }; 00118 00119 // <summary>Simple referenced counted pointer for constant data</summary> 00120 // <use visibility=export> 00121 // <reviewed reviewer="Friso Olnon" date="1995/03/15" tests="tCountedPtr" demos=""> 00122 00123 // <etymology> 00124 // This class is <em>Simple</em> because it does not have the 00125 // <src>operator->()</src> operator. This means that it puts less demands 00126 // on the underlying type. It is <em>Counted</em> because it is reference 00127 // counted, and it is <em>Const</em> because the underlying value is 00128 // non-modifiable. 00129 // </etymology> 00130 00131 // <synopsis> 00132 // This class implements a simple reference counting mechanism. It 00133 // allows <src>SimpleCountedConstPtr</src>s to be passed around freely, 00134 // incrementing or decrementing the reference count as needed when one 00135 // <src>SimpleCountedConstPtr</src> is assigned to another. When the 00136 // reference count reaches zero the internal storage is deleted by 00137 // default, but this behavior can be overridden. 00138 // 00139 // This class is used as a pointer to constant data. As such, it only 00140 // has the subset of the 00141 // <linkto class="CountedConstPtr:description">CountedConstPtr</linkto> 00142 // functions which are relevant for constant data. 00143 // </synopsis> 00144 00145 // <motivation> 00146 // Reference counting 00147 // </motivation> 00148 00149 template<class t> class SimpleCountedConstPtr 00150 { 00151 public: 00152 00153 // This constructor allows for the creation of a null 00154 // <src>SimpleCountedConstPtr</src>. The assignment operator can be used 00155 // to assign a null <src>SimpleCountedConstPtr</src> from another 00156 // pointer. 00157 // 00158 SimpleCountedConstPtr() : ref(0) {} 00159 00160 // This constructor sets up a reference count for the <src>val</src> 00161 // pointer. By default, the data pointed to by <src>val</src> 00162 // will be deleted when it is no longer referenced. Passing in 00163 // <src>False</src> for <src>delit</src> will prevent the data 00164 // from being deleted when the reference count reaches zero. 00165 // 00166 // <note role=warning> After the counted pointer is initialized 00167 // the value should no longer be manipulated by the raw pointer of 00168 // type <src>t*</src>. 00169 // </note> 00170 // 00171 SimpleCountedConstPtr(t *val, Bool delit = True) { 00172 ref = new PtrRep<t>(val,delit); 00173 } 00174 00175 // This constructor sets up a reference count for the 00176 // <src>val</src> pointer. Since <src>val</src> is a pointer to 00177 // constant data, the data will not be deleted when the reference 00178 // count reaches zero. 00179 // 00180 // <note role=tip> Since the constant data will NOT be cleaned up 00181 // when the reference count reaches zero, the use of this class for 00182 // pointers to constant data may not be desirable. 00183 // </note> 00184 // 00185 SimpleCountedConstPtr(const t *val) { 00186 ref = new PtrRep<t>((t *) val,False); 00187 } 00188 00189 // This copy constructor allows <src>SimpleCountedConstPtr</src>s to be 00190 // initialized from other <src>SimpleCountedConstPtr</src>s. 00191 // 00192 SimpleCountedConstPtr(const SimpleCountedConstPtr<t> &val) : ref(val.ref) { 00193 if (ref) 00194 (*ref).count++; 00195 } 00196 00197 // This destructor only deletes the really stored data when it was 00198 // initialized as deletable and the reference count is zero. 00199 // 00200 virtual ~SimpleCountedConstPtr(); 00201 00202 // The <src>SimpleCountedConstPtr</src> indirection operator simply 00203 // returns a reference to the value being protected. If the pointer 00204 // is un-initialized (null), an exception will be thrown. The member 00205 // function 00206 // <linkto class="SimpleCountedConstPtr:null()const">null</linkto>() 00207 // can be used to catch such a condition in time. 00208 // 00209 // <thrown> 00210 // <li> ExcpError 00211 // </thrown> 00212 // 00213 // <note role=tip> The address of the reference returned should 00214 // not be stored for later use. 00215 // </note> 00216 // 00217 const t &operator*() const { 00218 if (!ref) throw_Null_CountedPtr_dereference_error(); 00219 return(*(*ref).val); 00220 } 00221 00222 // Equality operator which checks to see if two 00223 // <src>SimpleCountedConstPtr</src>s are pointing at the same thing. 00224 // 00225 Bool operator==(const SimpleCountedConstPtr<t> &other) const { 00226 return (ref == other.ref ? True : False); 00227 } 00228 00229 // Non-equality operator which checks to see if two 00230 // <src>SimpleCountedConstPtr</src>s are not pointing at the same thing. 00231 // 00232 Bool operator!=(const SimpleCountedConstPtr<t> &other) const { 00233 return (ref != other.ref ? True : False); 00234 } 00235 00236 // This assignment operator allows <src>SimpleCountedConstPtr</src>s 00237 // to be freely assigned to each other. 00238 // 00239 SimpleCountedConstPtr<t> &operator=(const SimpleCountedConstPtr<t> &val) { 00240 if (ref && --(*ref).count == 0){ 00241 delete ref; 00242 ref = 0; 00243 } 00244 if ((ref = val.ref) != 0) 00245 (*ref).count++; 00246 return *this; 00247 } 00248 00249 // This assignment operator allows the object to which the current 00250 // <src>SimpleCountedConstPtr</src> points to be changed. 00251 // 00252 SimpleCountedConstPtr<t> &operator=(t *v); 00253 00254 // Sometimes it is useful to know if there is more than one 00255 // reference made. This is a way of getting that. Of course the point 00256 // of these classes is that this information is normally not required. 00257 // 00258 uInt nrefs() const {return ref->count;} 00259 00260 // This function changes the value for this 00261 // <src>SimpleCountedConstPtr</src> and all of the other 00262 // <src>SimpleCountedConstPtr</src>s which point to this same value. 00263 // 00264 // <note role=warning> This is dangerous, and generally should not 00265 // be done. 00266 // </note> 00267 // 00268 void replace(t *v, Bool delit = True) { 00269 if (ref && (v != (*ref).val)) { // Guarding against replacing ourselves 00270 (*ref).freeVal(); 00271 (*ref).val = v; 00272 (*ref).deletable = delit; 00273 } 00274 } 00275 00276 // Check to see if this <src>SimpleCountedConstPtr</src> is 00277 // un-initialized, null. 00278 // 00279 Bool null() const { return (ref==0 || (ref->val == 0));} 00280 00281 protected: 00282 00283 PtrRep<t> *ref; 00284 00285 }; 00286 00287 // <summary>Regular referenced counted pointer for constant data</summary> 00288 // <use visibility=export> 00289 // <reviewed reviewer="Friso Olnon" date="1995/03/15" tests="tCountedPtr" demos=""> 00290 00291 // <prerequisite> 00292 // <li> class <linkto class="SimpleCountedConstPtr:description">SimpleCountedConstPtr</linkto> 00293 // </prerequisite> 00294 00295 // <synopsis> 00296 // This class has the same objective as 00297 // <linkto class="SimpleCountedConstPtr:description">SimpleCountedConstPtr</linkto> 00298 // but it adds the <src>operator->()</src>. It still only contains a 00299 // pointer whose underlying data cannot be changed. The destructor 00300 // deletes the underlying data when the reference count reaches zero. 00301 // </synopsis> 00302 00303 // <motivation> 00304 // <src>operator->()</src> is useful, but not always available for 00305 // every type. 00306 // </motivation> 00307 00308 template<class t> class CountedConstPtr : virtual public SimpleCountedConstPtr<t> { 00309 public: 00310 00311 // This constructor allows for the creation of a null 00312 // <src>CountedConstPtr</src>. The assignment operator can be 00313 // used to assign a null <src>CountedConstPtr</src> from 00314 // another pointer. 00315 // 00316 CountedConstPtr() : SimpleCountedConstPtr<t>() {} 00317 00318 // This constructor sets up a reference count for the <src>val</src> 00319 // pointer. By default, the data pointed to by <src>val</src> will 00320 // be deleted when it is no longer referenced. Passing in 00321 // <src>False</src> for <src>delit</src> will prevent the data 00322 // from being deleted when the reference count reaches zero. 00323 // 00324 // <note role=warning> After the counted pointer is initialized 00325 // the value should no longer be manipulated by the raw pointer 00326 // of type <src>t*</src>. 00327 // </note> 00328 // 00329 CountedConstPtr(t *val, Bool delit = True) : SimpleCountedConstPtr<t>(val,delit) {} 00330 00331 // This copy constructor allows <src>CountedConstPtr</src>s to be 00332 // initialized from other <src>CountedConstPtr</src>s. 00333 // 00334 CountedConstPtr(const CountedConstPtr<t> &val) : SimpleCountedConstPtr<t>(val) {} 00335 00336 // This assignment operator allows <src>CountedConstPtr</src>s to be 00337 // freely assigned to each other. 00338 // 00339 CountedConstPtr<t> &operator=(const CountedConstPtr<t> &val) { 00340 SimpleCountedConstPtr<t>::operator=(val); 00341 return *this; 00342 } 00343 00344 // This assignment operator allows the object to which the current 00345 // <src>CountedConstPtr</src> points to be changed. 00346 // 00347 CountedConstPtr<t> &operator=(t *v) { 00348 SimpleCountedConstPtr<t>::operator=(v); 00349 return *this; 00350 } 00351 00352 // This dereferencing operator behaves as expected; it returns the 00353 // pointer to the value being protected, and then its dereferencing 00354 // operator will be invoked as appropriate. If the pointer is 00355 // un-initialized (null), an exception will be thrown. The member 00356 // function 00357 // <linkto class="SimpleCountedConstPtr:null()const">null</linkto>() 00358 // can be used to catch such a condition in time. 00359 // 00360 // <thrown> 00361 // <li> ExcpError 00362 // </thrown> 00363 // 00364 const t *operator->() const { 00365 if (!this->ref) throw_Null_CountedPtr_dereference_error(); 00366 return ((*this->ref).val); 00367 } 00368 }; 00369 00370 // <summary> Simple referenced counted pointer to non-constant data</summary> 00371 // <use visibility=export> 00372 // <reviewed reviewer="Friso Olnon" date="1995/03/15" tests="tCountedPtr" demos=""> 00373 00374 // <prerequisite> 00375 // <li> class <linkto class="SimpleCountedConstPtr:description">SimpleCountedConstPtr</linkto> 00376 // </prerequisite> 00377 00378 // <synopsis> 00379 // This class, like 00380 // <linkto class="SimpleCountedConstPtr:description">SimpleCountedConstPtr</linkto>, 00381 // does not define the <src>operator->()</src>. Thus it can point to 00382 // simple data which does not have this operator defined. In contrast to 00383 // <src>SimpleCountedConstPtr</src>, this class points at non-constant 00384 // underlying data. The deletion properties are the same for both 00385 // classes. 00386 // </synopsis> 00387 00388 template<class t> class SimpleCountedPtr : virtual public SimpleCountedConstPtr<t> { 00389 public: 00390 00391 // This constructor allows for the creation of a null 00392 // <src>SimpleCountedPtr</src>. The assignment operator can be used 00393 // to assign a null <src>SimpleCountedPtr</src> from another pointer. 00394 // 00395 SimpleCountedPtr() : SimpleCountedConstPtr<t>() {} 00396 00397 // This constructor sets up a reference count for the <src>val</src> 00398 // pointer. By default, the data pointed to by <src>val</src> 00399 // will be deleted when it is no longer referenced. Passing in 00400 // <src>False</src> for <src>delit</src> will prevent the data 00401 // from being deleted when the reference count reaches zero. 00402 // 00403 // <note role=warning> After the counted pointer is initialized 00404 // the value should no longer be manipulated by the raw pointer 00405 // of type <src>t*</src>. 00406 // </note> 00407 // 00408 SimpleCountedPtr(t *val, Bool delit = True) : SimpleCountedConstPtr<t>(val,delit) {} 00409 00410 // This copy constructor allows <src>SimpleCountedPtr</src>s to be 00411 // initialized from other <src>SimpleCountedPtr</src>s. 00412 // 00413 SimpleCountedPtr(const SimpleCountedPtr<t> &val) : SimpleCountedConstPtr<t>(val) {} 00414 00415 // This assignment operator allows <src>SimpleCountedPtr</src>s to be 00416 // freely assigned to each other. 00417 // 00418 SimpleCountedPtr<t> &operator=(const SimpleCountedPtr<t> &val) { 00419 SimpleCountedConstPtr<t>::operator=(val); 00420 return *this; 00421 } 00422 00423 // This assignment operator allows the object to which the current 00424 // <src>SimpleCountedPtr</src> points to be changed. 00425 // 00426 SimpleCountedPtr<t> &operator=(t *v) { 00427 SimpleCountedConstPtr<t>::operator=(v); 00428 return *this; 00429 } 00430 00431 // The <src>SimpleCountedPtr</src> indirection operator simply 00432 // returns a reference to the value being protected. If the pointer 00433 // is un-initialized (null), an exception will be thrown. The member 00434 // function 00435 // <linkto class="SimpleCountedConstPtr:null()const">null</linkto>() 00436 // can be used to catch such a condition in time. 00437 // 00438 // <thrown> 00439 // <li> ExcpError 00440 // </thrown> 00441 // 00442 // <note role=tip> The address of the reference returned should 00443 // not be stored for later use. 00444 // </note> 00445 // 00446 // <group> 00447 const t &operator*() const { 00448 if (!this->ref) throw_Null_CountedPtr_dereference_error(); 00449 return(*(*this->ref).val); 00450 } 00451 t &operator*() { 00452 if (!this->ref) throw_Null_CountedPtr_dereference_error(); 00453 return(*(*this->ref).val); 00454 } 00455 // </group> 00456 00457 }; 00458 00459 // <summary>Regular referenced counted pointer for non-constant data</summary> 00460 // <use visibility=export> 00461 // <reviewed reviewer="Friso Olnon" date="1995/03/15" tests="tCountedPtr" demos=""> 00462 00463 // <prerequisite> 00464 // <li> class <linkto class="SimpleCountedPtr:description">SimpleCountedPtr</linkto> 00465 // <li> class <linkto class="CountedConstPtr:description">CountedConstPtr</linkto> 00466 // </prerequisite> 00467 00468 // <synopsis> 00469 // This class completes the lattice. It inherits much of the members 00470 // which deal with non-constant data from 00471 // <linkto class="SimpleCountedPtr:description">SimpleCountedPtr</linkto>, 00472 // and it inherits the const <src>operator->()</src> from 00473 // <linkto class="CountedConstPtr:description">CountedConstPtr</linkto>. 00474 // What this class adds is the <src>operator->()</src> which returns a 00475 // modifiable pointer. 00476 // </synopsis> 00477 // 00478 template<class t> class CountedPtr : public SimpleCountedPtr<t>, 00479 public CountedConstPtr<t> { 00480 public: 00481 00482 // This constructor allows for the creation of a null 00483 // <src>CountedPtr</src>. The assignment operator can be used 00484 // to assign a null <src>CountedPtr</src> from another 00485 // pointer. 00486 // 00487 CountedPtr(); 00488 00489 // This constructor sets up a reference count for the 00490 // <src>val</src> pointer. By default, the data pointed to by 00491 // <src>val</src> will be deleted when it is no longer 00492 // referenced. Passing in <src>False</src> for <src>delit</src> will 00493 // prevent the data from being deleted when the reference count 00494 // reaches zero. 00495 // 00496 // <note role=warning> After the counted pointer is initialized 00497 // the value should no longer be manipulated by the raw pointer of 00498 // type <src>t*</src>. 00499 // </note> 00500 // 00501 CountedPtr(t *val, Bool delit = True); 00502 00503 // This copy constructor allows <src>CountedPtr</src>s to be 00504 // initialized from other <src>CountedPtr</src>s. 00505 // 00506 CountedPtr(const CountedPtr<t> &val); 00507 00508 // This assignment operator allows <src>CountedPtr</src>s to be 00509 // freely assigned to each other. 00510 // 00511 CountedPtr<t> &operator=(const CountedPtr<t> &val) { 00512 SimpleCountedPtr<t>::operator=(val); 00513 return *this; 00514 } 00515 00516 // This assignment operator allows the object to which the current 00517 // <src>CountedPtr</src> points to be changed. 00518 // 00519 CountedPtr<t> &operator=(t *v) { 00520 SimpleCountedPtr<t>::operator=(v); 00521 return *this; 00522 } 00523 00524 // This dereferencing operator behaves as expected; it returns the 00525 // pointer to the value being protected, and then its dereferencing 00526 // operator will be invoked as appropriate. If the pointer is 00527 // un-initialized (null), an exception will be thrown. The member 00528 // function 00529 // <linkto class="SimpleCountedConstPtr:null()const">null</linkto>() 00530 // can be used to catch such a condition in time. 00531 // 00532 // <thrown> 00533 // <li> ExcpError 00534 // </thrown> 00535 // 00536 // <group> 00537 t *operator->() const { 00538 if (!this->ref) throw_Null_CountedPtr_dereference_error(); 00539 return ((*this->ref).val); 00540 } 00541 t *operator->() { 00542 if (!this->ref) throw_Null_CountedPtr_dereference_error(); 00543 return ((*this->ref).val); 00544 } 00545 // </group> 00546 }; 00547 00548 } //#End casa namespace 00549 #ifndef AIPS_NO_TEMPLATE_SRC 00550 #include <casa/Utilities/CountedPtr.cc> 00551 #include <casa/Utilities/CountedPtr2.cc> 00552 #endif //# AIPS_NO_TEMPLATE_SRC 00553 #endif
1.5.1