00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
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 #if REF_CHECK_STACK
00133 #include <unistd.h>
00134 #ifndef HAVE_SBRK_DEC
00135 extern "C" void * sbrk(ssize_t);
00136 #endif
00137 #define DO_REF_CHECK_STACK(p) (((void*) (p) > sbrk(0)) && (p)->managed())
00138 #else // REF_CHECK_STACK
00139 #define DO_REF_CHECK_STACK(p) (0)
00140 #endif // REF_CHECK_STACK
00141
00142 #if REF_MANAGE
00143 #define DO_REF_UNMANAGE(p) ((p)->unmanage())
00144 #else // REF_MANAGE
00145 #define DO_REF_UNMANAGE(p)
00146 #endif // REF_MANAGE
00147
00148 #if REF_USE_LOCKS
00149 #define __REF_LOCK__(p) p->lock_ptr()
00150 #define __REF_UNLOCK__(p) p->unlock_ptr()
00151 #define __REF_INITLOCK__() ref_lock_ = 0xff
00152 #else
00153 #define __REF_LOCK__(p)
00154 #define __REF_UNLOCK__(p)
00155 #define __REF_INITLOCK__()
00156 #endif
00157
00158 typedef unsigned long refcount_t;
00159
00184 class RefCount: public Identity {
00185 private:
00186 #if REF_MANAGE
00187 # define REF_MAX_NREF (UINT_MAX - 1)
00188 # define REF_MANAGED_CODE UINT_MAX
00189 #else
00190 # define REF_MAX_NREF UINT_MAX
00191 #endif
00192 unsigned int _reference_count_;
00193 #if REF_USE_LOCKS
00194 unsigned char ref_lock_;
00195 #endif
00196
00197 void error(const char*) const;
00198 void too_many_refs() const;
00199 void not_enough_refs() const;
00200 protected:
00201 RefCount(): _reference_count_(0) {
00202 __REF_INITLOCK__();
00203
00204 }
00205 RefCount(const RefCount&): _reference_count_(0) {
00206 __REF_INITLOCK__();
00207
00208 }
00209
00210
00211 RefCount& operator=(const RefCount&) { return *this; }
00212 public:
00213 virtual ~RefCount();
00214
00216 int lock_ptr() const;
00218 int unlock_ptr() const;
00219
00221 void use_locks(bool inVal);
00222
00224 refcount_t nreference() const {
00225 # if REF_MANAGE
00226 if (!managed()) return 1;
00227 # endif
00228 return _reference_count_;
00229 }
00230
00232 refcount_t reference() {
00233 # if REF_MANAGE
00234 if (!managed()) return 1;
00235 # endif
00236 __REF_LOCK__(this);
00237 # if REF_CHECK_MAX_NREF
00238 if (_reference_count_ >= REF_MAX_NREF) too_many_refs();
00239 # endif
00240 _reference_count_++;
00241 refcount_t r = _reference_count_;
00242 __REF_UNLOCK__(this);
00243 return r;
00244 }
00245
00247 refcount_t dereference() {
00248 # if REF_MANAGE
00249 if (!managed()) return 1;
00250 # endif
00251 __REF_LOCK__(this);
00252 # if REF_CHECK_MIN_NREF
00253 if (_reference_count_ == 0) not_enough_refs();
00254 # endif
00255 _reference_count_--;
00256 refcount_t r = _reference_count_;
00257 __REF_UNLOCK__(this);
00258 return r;
00259 }
00260
00261 #if REF_MANAGE
00262 int managed() const {
00263 return _reference_count_ != REF_MANAGED_CODE;
00264 }
00270 void unmanage() {
00271 _reference_count_ = REF_MANAGED_CODE;
00272 }
00273 #else // REF_MANAGE
00274
00275 int managed() const { return 1; }
00276 #endif // REF_MANAGE
00277 };
00278
00282 class RefBase {
00283 protected:
00285 void warn ( const char * msg) const;
00287 void warn_ref_to_stack() const;
00289 void warn_skip_stack_delete() const;
00291 void warn_bad_ref_count() const;
00293 void ref_info(RefCount*p,std::ostream& os) const;
00294 void ref_info(std::ostream& os) const;
00295 void check_pointer() const;
00296 void reference(RefCount *);
00297 int dereference(RefCount *);
00298 public:
00299 virtual ~RefBase();
00301 virtual RefCount* parentpointer() const = 0;
00304 void require_nonnull() const;
00305 };
00306
00320 template <class T>
00321 class Ref : public RefBase {
00322 private:
00323 T* p;
00324 public:
00326 Ref(): p(0) {}
00328 Ref(T*a) : p(0)
00329 {
00330 if (a) {
00331 p = a;
00332 reference(p);
00333 }
00334 }
00336 Ref(const Ref<T> &a) : p(0)
00337 {
00338 if (a.pointer()) {
00339 p = a.pointer();
00340 reference(p);
00341 }
00342 }
00344 template <class A> Ref(const Ref<A> &a): p(0)
00345 {
00346 if (a.pointer()) {
00347 p = a.pointer();
00348 reference(p);
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00364 ~Ref()
00365 {
00366 clear();
00367 }
00370 T* operator->() const { return p; }
00372 T* pointer() const { return p; }
00374 RefCount *parentpointer() const { return p; }
00375
00376 operator T*() const { return p; }
00379 T& operator *() const { return *p; };
00382 int null() const { return p == 0; }
00384 int nonnull() const { return p != 0; }
00387 template <class A> int operator==(const Ref<A>&a) const
00388 { return eq(p,a.pointer()); }
00389 template <class A> int operator>=(const Ref<A>&a) const
00390 { return ge(p,a.pointer()); }
00391 template <class A> int operator<=(const Ref<A>&a) const
00392 { return le(p,a.pointer()); }
00393 template <class A> int operator>(const Ref<A>&a) const
00394 { return gt(p,a.pointer()); }
00395 template <class A> int operator<(const Ref<A>&a) const
00396 { return lt(p,a.pointer()); }
00397 template <class A> int operator!=(const Ref<A>&a) const
00398 { return ne(p,a.pointer()); }
00401 int compare(const Ref<T> &a) const {
00402 return eq(p,a.p)?0:((lt(p,a.p)?-1:1));
00403 }
00405 void clear()
00406 {
00407 if (p) {
00408 int ref = dereference(p);
00409 if (ref == 0)
00410 delete p;
00411 p = 0;
00412 }
00413 }
00415 Ref<T>& operator=(const Ref<T> & c)
00416 {
00417 T *cp = c.pointer();
00418 if (cp) {
00419 cp->reference();
00420 clear();
00421 p=cp;
00422 }
00423 else {
00424 clear();
00425 }
00426 return *this;
00427 }
00429 template <class A> Ref<T>& operator=(const Ref<A> & c)
00430 {
00431 A *cp = c.pointer();
00432 if (cp) {
00433 cp->reference();
00434 clear();
00435 p=cp;
00436 }
00437 else {
00438 clear();
00439 }
00440 return *this;
00441 }
00443 Ref<T>& operator<<(const RefBase&a) {
00444 T* cr = dynamic_cast<T*>(a.parentpointer());
00445 if (cr) {
00446 reference(cr);
00447 clear();
00448 }
00449 p = cr;
00450 return *this;
00451 }
00455 Ref<T>& operator<<(RefCount *a) {
00456 T* cr = dynamic_cast<T*>(a);
00457 if (cr) assign_pointer(cr);
00458 else if (a && a->nreference() <= 0) delete a;
00459 return *this;
00460 }
00462 Ref<T>& operator=(T* cr)
00463 {
00464 assign_pointer(cr);
00465 return *this;
00466 }
00468 void assign_pointer(T* cr)
00469 {
00470 if (cr) {
00471 if (DO_REF_CHECK_STACK(cr)) {
00472 DO_REF_UNMANAGE(cr);
00473 warn_ref_to_stack();
00474 }
00475 cr->reference();
00476 }
00477 clear();
00478 p = cr;
00479 }
00481 void check_pointer() const
00482 {
00483 if (p && p->nreference() <= 0) {
00484 warn_bad_ref_count();
00485 }
00486 }
00488 void ref_info(std::ostream& os) const
00489 {
00490 RefBase::ref_info(p,os);
00491 }
00493 void warn(const char*s) const { RefBase::warn(s); }
00494 };
00495
00496 #endif
00497
00498
00499
00500
00501
00502
00503