MPQC
2.3.1
|
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 RefBase() {}; 00310 virtual ~RefBase(); 00312 virtual RefCount* parentpointer() const = 0; 00315 void require_nonnull() const; 00316 }; 00317 00331 template <class T> 00332 class Ref : public RefBase { 00333 private: 00334 T* p; 00335 public: 00337 Ref(): p(0) {} 00339 Ref(T*a) : p(0) 00340 { 00341 if (a) { 00342 p = a; 00343 reference(p); 00344 } 00345 } 00347 Ref(const Ref<T> &a) : p(0) 00348 { 00349 if (a.pointer()) { 00350 p = a.pointer(); 00351 reference(p); 00352 } 00353 } 00355 template <class A> Ref(const Ref<A> &a): p(0) 00356 { 00357 if (a.pointer()) { 00358 p = a.pointer(); 00359 reference(p); 00360 } 00361 } 00362 // /** Create a reference to the object a. Do a 00363 // dynamic_cast to convert a to the appropiate type. */ 00364 // Ref(const RefBase&a) { 00365 // p = dynamic_cast<T*>(a.parentpointer()); 00366 // reference(p); 00367 // } 00368 // /** Create a reference to the object a. Do a 00369 // dynamic_cast to convert a to the appropiate type. */ 00370 // Ref(RefCount*a): p(0) { 00371 // operator<<(a); 00372 // } 00375 ~Ref() 00376 { 00377 clear(); 00378 } 00381 T* operator->() const { return p; } 00383 T* pointer() const { return p; } 00385 RefCount *parentpointer() const { return p; } 00386 00387 operator T*() const { return p; } 00390 T& operator *() const { return *p; }; 00393 int null() const { return p == 0; } 00395 int nonnull() const { return p != 0; } 00398 template <class A> int operator==(const Ref<A>&a) const 00399 { return eq(p,a.pointer()); } 00400 template <class A> int operator>=(const Ref<A>&a) const 00401 { return ge(p,a.pointer()); } 00402 template <class A> int operator<=(const Ref<A>&a) const 00403 { return le(p,a.pointer()); } 00404 template <class A> int operator>(const Ref<A>&a) const 00405 { return gt(p,a.pointer()); } 00406 template <class A> int operator<(const Ref<A>&a) const 00407 { return lt(p,a.pointer()); } 00408 template <class A> int operator!=(const Ref<A>&a) const 00409 { return ne(p,a.pointer()); } 00412 int compare(const Ref<T> &a) const { 00413 return eq(p,a.p)?0:((lt(p,a.p)?-1:1)); 00414 } 00416 void clear() 00417 { 00418 if (p) { 00419 int ref = dereference(p); 00420 if (ref == 0) 00421 delete p; 00422 p = 0; 00423 } 00424 } 00426 Ref<T>& operator=(const Ref<T> & c) 00427 { 00428 T *cp = c.pointer(); 00429 if (cp) { 00430 cp->reference(); 00431 clear(); 00432 p=cp; 00433 } 00434 else { 00435 clear(); 00436 } 00437 return *this; 00438 } 00440 template <class A> Ref<T>& operator=(const Ref<A> & c) 00441 { 00442 A *cp = c.pointer(); 00443 if (cp) { 00444 cp->reference(); 00445 clear(); 00446 p=cp; 00447 } 00448 else { 00449 clear(); 00450 } 00451 return *this; 00452 } 00454 Ref<T>& operator<<(const RefBase&a) { 00455 T* cr = dynamic_cast<T*>(a.parentpointer()); 00456 if (cr) { 00457 reference(cr); 00458 clear(); 00459 } 00460 p = cr; 00461 return *this; 00462 } 00466 Ref<T>& operator<<(RefCount *a) { 00467 T* cr = dynamic_cast<T*>(a); 00468 if (cr) assign_pointer(cr); 00469 else if (a && a->nreference() <= 0) delete a; 00470 return *this; 00471 } 00473 Ref<T>& operator=(T* cr) 00474 { 00475 assign_pointer(cr); 00476 return *this; 00477 } 00479 void assign_pointer(T* cr) 00480 { 00481 if (cr) { 00482 if (DO_REF_CHECK_STACK(cr)) { 00483 DO_REF_UNMANAGE(cr); 00484 warn_ref_to_stack(); 00485 } 00486 cr->reference(); 00487 } 00488 clear(); 00489 p = cr; 00490 } 00492 void check_pointer() const 00493 { 00494 if (p && p->nreference() <= 0) { 00495 warn_bad_ref_count(); 00496 } 00497 } 00499 void ref_info(std::ostream& os) const 00500 { 00501 RefBase::ref_info(p,os); 00502 } 00504 void warn(const char*s) const { RefBase::warn(s); } 00505 }; 00506 00507 } 00508 00509 #endif 00510 00511 // /////////////////////////////////////////////////////////////////////////// 00512 00513 // Local Variables: 00514 // mode: c++ 00515 // c-file-style: "CLJ" 00516 // End: