Main Page | Class Hierarchy | Class List | File List | Class Members | Related Pages

ref.h

00001 // 00002 // ref.h --- definitions of the reference counting classes 00003 // 00004 // Copyright (C) 1996 Limit Point Systems, Inc. 00005 // 00006 // Author: Curtis Janssen <cljanss@limitpt.com> 00007 // Maintainer: LPS 00008 // 00009 // This file is part of the SC Toolkit. 00010 // 00011 // The SC Toolkit is free software; you can redistribute it and/or modify 00012 // it under the terms of the GNU Library General Public License as published by 00013 // the Free Software Foundation; either version 2, or (at your option) 00014 // any later version. 00015 // 00016 // The SC Toolkit is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 // GNU Library General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU Library General Public License 00022 // along with the SC Toolkit; see the file COPYING.LIB. If not, write to 00023 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 00024 // 00025 // The U.S. Government is granted a limited license as per AL 91-7. 00026 // 00027 00028 // This is the main include file for the reference counting classes. 00029 // This includes two other files: reftmpl.h and refmacr.h. The 00030 // former is a template declaration for the reference counted classes 00031 // and the latter is generated from the former by a perl script and 00032 // provides CPP macros that declare reference counting classes. 00033 // 00034 // The behaviour of the package can be modified with the following five 00035 // macros, each of which should be undefined, 0, or 1: 00036 // 00037 // REF_CHECK_STACK: If this is 1 referenced objects are checked to see if they 00038 // reside on the stack, in which case storage for the object is not managed, 00039 // if management is enabled. This feature can be confused by multiple threads 00040 // and memory checking libraries. 00041 // 00042 // REF_MANAGE: If this is 1 the manage and unmanage members are enabled. 00043 // 00044 // REF_CHECK_MAX_NREF: If this is 1 the reference count is checked before 00045 // it is incremented to make sure it isn't too big. 00046 // 00047 // REF_CHECK_MIN_NREF: If this is 1 the reference count is checked before 00048 // it is decremented to make sure it isn't already zero. 00049 // 00050 // REF_USE_LOCKS: If this is 1 then critical regions are locked before they 00051 // are entered. This prevents erroneous behavior when multiple threads 00052 // share reference counted objects. This will slow down certain operations, 00053 // so it should be set to 0 if your application does not need to be thread 00054 // safe. 00055 // 00056 // If a macro is undefined, then the behaviour is architecture 00057 // dependent--usually, the macro will be set to 1 in this case. 00058 // For maximum efficiency and for normal operation after the program is 00059 // debugged, compile with all of the above macros defined to zero. 00060 // This can also be done with -DREF_OPTIMIZE. 00061 // 00062 // An include file can be used to set these options as well. This has 00063 // the advantage that dependency checking will force an automatic 00064 // recompile of all affected files if the options change. The file 00065 // <scconfig.h> will be include if -DHAVE_CONFIG_H is specified. 00066 // 00067 // Note that all source code that uses references must be compiled with 00068 // the same value REF_MANAGE. Changing this can change the storage layout 00069 // and the interpretation of the reference count data. 00070 00071 00072 #ifdef __GNUC__ 00073 #pragma interface 00074 #endif 00075 00076 #ifndef _util_ref_ref_h 00077 #define _util_ref_ref_h 00078 00079 #include <iostream> 00080 #include <stdlib.h> 00081 #include <limits.h> 00082 00083 #include <util/ref/identity.h> 00084 00085 #ifdef HAVE_CONFIG_H 00086 #include <scconfig.h> 00087 #endif 00088 00089 #ifdef REF_OPTIMIZE 00090 #ifndef REF_CHECK_STACK 00091 # define REF_CHECK_STACK 0 00092 #endif 00093 #ifndef REF_MANAGE 00094 # define REF_MANAGE 0 00095 #endif 00096 #ifndef REF_CHECK_MAX_NREF 00097 # define REF_CHECK_MAX_NREF 0 00098 #endif 00099 #ifndef REF_CHECK_MIN_NREF 00100 # define REF_CHECK_MIN_NREF 0 00101 #endif 00102 #endif 00103 00104 #ifdef SUNMOS 00105 #ifndef REF_CHECK_STACK 00106 #define REF_CHECK_STACK 0 00107 #endif 00108 #else 00109 #ifndef REF_CHECK_STACK 00110 #define REF_CHECK_STACK 0 00111 #endif 00112 #endif 00113 00114 #ifndef REF_MANAGE 00115 #define REF_MANAGE 1 00116 #endif 00117 00118 #ifndef REF_CHECK_MAX_NREF 00119 #define REF_CHECK_MAX_NREF 1 00120 #endif 00121 00122 #ifndef REF_CHECK_MIN_NREF 00123 #define REF_CHECK_MIN_NREF 1 00124 #endif 00125 00126 #ifndef REF_USE_LOCKS 00127 # if HAVE_STHREAD || HAVE_CREATETHREAD || HAVE_PTHREAD 00128 # define REF_USE_LOCKS 1 00129 # endif 00130 #endif 00131 00132 #ifndef REF_ALWAYS_USE_LOCKS 00133 # define REF_ALWAYS_USE_LOCKS 1 00134 #endif 00135 00136 #if REF_CHECK_STACK 00137 #include <unistd.h> 00138 #ifndef HAVE_SBRK_DEC 00139 extern "C" void * sbrk(ssize_t); 00140 #endif 00141 #define DO_REF_CHECK_STACK(p) (((void*) (p) > sbrk(0)) && (p)->managed()) 00142 #else // REF_CHECK_STACK 00143 #define DO_REF_CHECK_STACK(p) (0) 00144 #endif // REF_CHECK_STACK 00145 00146 #if REF_MANAGE 00147 #define DO_REF_UNMANAGE(p) ((p)->unmanage()) 00148 #else // REF_MANAGE 00149 #define DO_REF_UNMANAGE(p) 00150 #endif // REF_MANAGE 00151 00152 #if REF_USE_LOCKS 00153 #define __REF_LOCK__(p) p->lock_ptr() 00154 #define __REF_UNLOCK__(p) p->unlock_ptr() 00155 #if REF_ALWAYS_USE_LOCKS 00156 #define __REF_INITLOCK__() use_locks(true) 00157 #else 00158 #define __REF_INITLOCK__() ref_lock_ = 0xff 00159 #endif 00160 #else 00161 #define __REF_LOCK__(p) 00162 #define __REF_UNLOCK__(p) 00163 #define __REF_INITLOCK__() 00164 #endif 00165 00166 namespace sc { 00167 00168 typedef unsigned long refcount_t; 00169 00194 class RefCount: public Identity { 00195 private: 00196 #if REF_MANAGE 00197 # define REF_MAX_NREF (UINT_MAX - 1) 00198 # define REF_MANAGED_CODE UINT_MAX 00199 #else 00200 # define REF_MAX_NREF UINT_MAX 00201 #endif 00202 unsigned int _reference_count_; 00203 #if REF_USE_LOCKS 00204 unsigned char ref_lock_; 00205 #endif 00206 00207 void error(const char*) const; 00208 void too_many_refs() const; 00209 void not_enough_refs() const; 00210 protected: 00211 RefCount(): _reference_count_(0) { 00212 __REF_INITLOCK__(); 00213 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl; 00214 } 00215 RefCount(const RefCount&): _reference_count_(0) { 00216 __REF_INITLOCK__(); 00217 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl; 00218 } 00219 00220 // Assigment should not overwrite the reference count. 00221 RefCount& operator=(const RefCount&) { return *this; } 00222 public: 00223 virtual ~RefCount(); 00224 00226 int lock_ptr() const; 00228 int unlock_ptr() const; 00229 00231 void use_locks(bool inVal); 00232 00234 refcount_t nreference() const { 00235 # if REF_MANAGE 00236 if (!managed()) return 1; 00237 # endif 00238 return _reference_count_; 00239 } 00240 00242 refcount_t reference() { 00243 # if REF_MANAGE 00244 if (!managed()) return 1; 00245 # endif 00246 __REF_LOCK__(this); 00247 # if REF_CHECK_MAX_NREF 00248 if (_reference_count_ >= REF_MAX_NREF) too_many_refs(); 00249 # endif 00250 _reference_count_++; 00251 refcount_t r = _reference_count_; 00252 __REF_UNLOCK__(this); 00253 return r; 00254 } 00255 00257 refcount_t dereference() { 00258 # if REF_MANAGE 00259 if (!managed()) return 1; 00260 # endif 00261 __REF_LOCK__(this); 00262 # if REF_CHECK_MIN_NREF 00263 if (_reference_count_ == 0) not_enough_refs(); 00264 # endif 00265 _reference_count_--; 00266 refcount_t r = _reference_count_; 00267 __REF_UNLOCK__(this); 00268 return r; 00269 } 00270 00271 #if REF_MANAGE 00272 int managed() const { 00273 return _reference_count_ != REF_MANAGED_CODE; 00274 } 00280 void unmanage() { 00281 _reference_count_ = REF_MANAGED_CODE; 00282 } 00283 #else // REF_MANAGE 00284 00285 int managed() const { return 1; } 00286 #endif // REF_MANAGE 00287 }; 00288 00292 class RefBase { 00293 protected: 00295 void warn ( const char * msg) const; 00297 void warn_ref_to_stack() const; 00299 void warn_skip_stack_delete() const; 00301 void warn_bad_ref_count() const; 00303 void ref_info(RefCount*p,std::ostream& os) const; 00304 void ref_info(std::ostream& os) const; 00305 void check_pointer() const; 00306 void reference(RefCount *); 00307 int dereference(RefCount *); 00308 public: 00309 virtual ~RefBase(); 00311 virtual RefCount* parentpointer() const = 0; 00314 void require_nonnull() const; 00315 }; 00316 00330 template <class T> 00331 class Ref : public RefBase { 00332 private: 00333 T* p; 00334 public: 00336 Ref(): p(0) {} 00338 Ref(T*a) : p(0) 00339 { 00340 if (a) { 00341 p = a; 00342 reference(p); 00343 } 00344 } 00346 Ref(const Ref<T> &a) : p(0) 00347 { 00348 if (a.pointer()) { 00349 p = a.pointer(); 00350 reference(p); 00351 } 00352 } 00354 template <class A> Ref(const Ref<A> &a): p(0) 00355 { 00356 if (a.pointer()) { 00357 p = a.pointer(); 00358 reference(p); 00359 } 00360 } 00361 // /** Create a reference to the object a. Do a 00362 // dynamic_cast to convert a to the appropiate type. */ 00363 // Ref(const RefBase&a) { 00364 // p = dynamic_cast<T*>(a.parentpointer()); 00365 // reference(p); 00366 // } 00367 // /** Create a reference to the object a. Do a 00368 // dynamic_cast to convert a to the appropiate type. */ 00369 // Ref(RefCount*a): p(0) { 00370 // operator<<(a); 00371 // } 00374 ~Ref() 00375 { 00376 clear(); 00377 } 00380 T* operator->() const { return p; } 00382 T* pointer() const { return p; } 00384 RefCount *parentpointer() const { return p; } 00385 00386 operator T*() const { return p; } 00389 T& operator *() const { return *p; }; 00392 int null() const { return p == 0; } 00394 int nonnull() const { return p != 0; } 00397 template <class A> int operator==(const Ref<A>&a) const 00398 { return eq(p,a.pointer()); } 00399 template <class A> int operator>=(const Ref<A>&a) const 00400 { return ge(p,a.pointer()); } 00401 template <class A> int operator<=(const Ref<A>&a) const 00402 { return le(p,a.pointer()); } 00403 template <class A> int operator>(const Ref<A>&a) const 00404 { return gt(p,a.pointer()); } 00405 template <class A> int operator<(const Ref<A>&a) const 00406 { return lt(p,a.pointer()); } 00407 template <class A> int operator!=(const Ref<A>&a) const 00408 { return ne(p,a.pointer()); } 00411 int compare(const Ref<T> &a) const { 00412 return eq(p,a.p)?0:((lt(p,a.p)?-1:1)); 00413 } 00415 void clear() 00416 { 00417 if (p) { 00418 int ref = dereference(p); 00419 if (ref == 0) 00420 delete p; 00421 p = 0; 00422 } 00423 } 00425 Ref<T>& operator=(const Ref<T> & c) 00426 { 00427 T *cp = c.pointer(); 00428 if (cp) { 00429 cp->reference(); 00430 clear(); 00431 p=cp; 00432 } 00433 else { 00434 clear(); 00435 } 00436 return *this; 00437 } 00439 template <class A> Ref<T>& operator=(const Ref<A> & c) 00440 { 00441 A *cp = c.pointer(); 00442 if (cp) { 00443 cp->reference(); 00444 clear(); 00445 p=cp; 00446 } 00447 else { 00448 clear(); 00449 } 00450 return *this; 00451 } 00453 Ref<T>& operator<<(const RefBase&a) { 00454 T* cr = dynamic_cast<T*>(a.parentpointer()); 00455 if (cr) { 00456 reference(cr); 00457 clear(); 00458 } 00459 p = cr; 00460 return *this; 00461 } 00465 Ref<T>& operator<<(RefCount *a) { 00466 T* cr = dynamic_cast<T*>(a); 00467 if (cr) assign_pointer(cr); 00468 else if (a && a->nreference() <= 0) delete a; 00469 return *this; 00470 } 00472 Ref<T>& operator=(T* cr) 00473 { 00474 assign_pointer(cr); 00475 return *this; 00476 } 00478 void assign_pointer(T* cr) 00479 { 00480 if (cr) { 00481 if (DO_REF_CHECK_STACK(cr)) { 00482 DO_REF_UNMANAGE(cr); 00483 warn_ref_to_stack(); 00484 } 00485 cr->reference(); 00486 } 00487 clear(); 00488 p = cr; 00489 } 00491 void check_pointer() const 00492 { 00493 if (p && p->nreference() <= 0) { 00494 warn_bad_ref_count(); 00495 } 00496 } 00498 void ref_info(std::ostream& os) const 00499 { 00500 RefBase::ref_info(p,os); 00501 } 00503 void warn(const char*s) const { RefBase::warn(s); } 00504 }; 00505 00506 } 00507 00508 #endif 00509 00510 // /////////////////////////////////////////////////////////////////////////// 00511 00512 // Local Variables: 00513 // mode: c++ 00514 // c-file-style: "CLJ" 00515 // End:

Generated at Thu Jul 29 19:53:51 2004 for MPQC 2.2.1 using the documentation package Doxygen 1.3.7.