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 namespace sc {
00159
00160 typedef unsigned long refcount_t;
00161
00186 class RefCount: public Identity {
00187 private:
00188 #if REF_MANAGE
00189 # define REF_MAX_NREF (UINT_MAX - 1)
00190 # define REF_MANAGED_CODE UINT_MAX
00191 #else
00192 # define REF_MAX_NREF UINT_MAX
00193 #endif
00194 unsigned int _reference_count_;
00195 #if REF_USE_LOCKS
00196 unsigned char ref_lock_;
00197 #endif
00198
00199 void error(const char*) const;
00200 void too_many_refs() const;
00201 void not_enough_refs() const;
00202 protected:
00203 RefCount(): _reference_count_(0) {
00204 __REF_INITLOCK__();
00205
00206 }
00207 RefCount(const RefCount&): _reference_count_(0) {
00208 __REF_INITLOCK__();
00209
00210 }
00211
00212
00213 RefCount& operator=(const RefCount&) { return *this; }
00214 public:
00215 virtual ~RefCount();
00216
00218 int lock_ptr() const;
00220 int unlock_ptr() const;
00221
00223 void use_locks(bool inVal);
00224
00226 refcount_t nreference() const {
00227 # if REF_MANAGE
00228 if (!managed()) return 1;
00229 # endif
00230 return _reference_count_;
00231 }
00232
00234 refcount_t reference() {
00235 # if REF_MANAGE
00236 if (!managed()) return 1;
00237 # endif
00238 __REF_LOCK__(this);
00239 # if REF_CHECK_MAX_NREF
00240 if (_reference_count_ >= REF_MAX_NREF) too_many_refs();
00241 # endif
00242 _reference_count_++;
00243 refcount_t r = _reference_count_;
00244 __REF_UNLOCK__(this);
00245 return r;
00246 }
00247
00249 refcount_t dereference() {
00250 # if REF_MANAGE
00251 if (!managed()) return 1;
00252 # endif
00253 __REF_LOCK__(this);
00254 # if REF_CHECK_MIN_NREF
00255 if (_reference_count_ == 0) not_enough_refs();
00256 # endif
00257 _reference_count_--;
00258 refcount_t r = _reference_count_;
00259 __REF_UNLOCK__(this);
00260 return r;
00261 }
00262
00263 #if REF_MANAGE
00264 int managed() const {
00265 return _reference_count_ != REF_MANAGED_CODE;
00266 }
00272 void unmanage() {
00273 _reference_count_ = REF_MANAGED_CODE;
00274 }
00275 #else // REF_MANAGE
00276
00277 int managed() const { return 1; }
00278 #endif // REF_MANAGE
00279 };
00280
00284 class RefBase {
00285 protected:
00287 void warn ( const char * msg) const;
00289 void warn_ref_to_stack() const;
00291 void warn_skip_stack_delete() const;
00293 void warn_bad_ref_count() const;
00295 void ref_info(RefCount*p,std::ostream& os) const;
00296 void ref_info(std::ostream& os) const;
00297 void check_pointer() const;
00298 void reference(RefCount *);
00299 int dereference(RefCount *);
00300 public:
00301 virtual ~RefBase();
00303 virtual RefCount* parentpointer() const = 0;
00306 void require_nonnull() const;
00307 };
00308
00322 template <class T>
00323 class Ref : public RefBase {
00324 private:
00325 T* p;
00326 public:
00328 Ref(): p(0) {}
00330 Ref(T*a) : p(0)
00331 {
00332 if (a) {
00333 p = a;
00334 reference(p);
00335 }
00336 }
00338 Ref(const Ref<T> &a) : p(0)
00339 {
00340 if (a.pointer()) {
00341 p = a.pointer();
00342 reference(p);
00343 }
00344 }
00346 template <class A> Ref(const Ref<A> &a): p(0)
00347 {
00348 if (a.pointer()) {
00349 p = a.pointer();
00350 reference(p);
00351 }
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00366 ~Ref()
00367 {
00368 clear();
00369 }
00372 T* operator->() const { return p; }
00374 T* pointer() const { return p; }
00376 RefCount *parentpointer() const { return p; }
00377
00378 operator T*() const { return p; }
00381 T& operator *() const { return *p; };
00384 int null() const { return p == 0; }
00386 int nonnull() const { return p != 0; }
00389 template <class A> int operator==(const Ref<A>&a) const
00390 { return eq(p,a.pointer()); }
00391 template <class A> int operator>=(const Ref<A>&a) const
00392 { return ge(p,a.pointer()); }
00393 template <class A> int operator<=(const Ref<A>&a) const
00394 { return le(p,a.pointer()); }
00395 template <class A> int operator>(const Ref<A>&a) const
00396 { return gt(p,a.pointer()); }
00397 template <class A> int operator<(const Ref<A>&a) const
00398 { return lt(p,a.pointer()); }
00399 template <class A> int operator!=(const Ref<A>&a) const
00400 { return ne(p,a.pointer()); }
00403 int compare(const Ref<T> &a) const {
00404 return eq(p,a.p)?0:((lt(p,a.p)?-1:1));
00405 }
00407 void clear()
00408 {
00409 if (p) {
00410 int ref = dereference(p);
00411 if (ref == 0)
00412 delete p;
00413 p = 0;
00414 }
00415 }
00417 Ref<T>& operator=(const Ref<T> & c)
00418 {
00419 T *cp = c.pointer();
00420 if (cp) {
00421 cp->reference();
00422 clear();
00423 p=cp;
00424 }
00425 else {
00426 clear();
00427 }
00428 return *this;
00429 }
00431 template <class A> Ref<T>& operator=(const Ref<A> & c)
00432 {
00433 A *cp = c.pointer();
00434 if (cp) {
00435 cp->reference();
00436 clear();
00437 p=cp;
00438 }
00439 else {
00440 clear();
00441 }
00442 return *this;
00443 }
00445 Ref<T>& operator<<(const RefBase&a) {
00446 T* cr = dynamic_cast<T*>(a.parentpointer());
00447 if (cr) {
00448 reference(cr);
00449 clear();
00450 }
00451 p = cr;
00452 return *this;
00453 }
00457 Ref<T>& operator<<(RefCount *a) {
00458 T* cr = dynamic_cast<T*>(a);
00459 if (cr) assign_pointer(cr);
00460 else if (a && a->nreference() <= 0) delete a;
00461 return *this;
00462 }
00464 Ref<T>& operator=(T* cr)
00465 {
00466 assign_pointer(cr);
00467 return *this;
00468 }
00470 void assign_pointer(T* cr)
00471 {
00472 if (cr) {
00473 if (DO_REF_CHECK_STACK(cr)) {
00474 DO_REF_UNMANAGE(cr);
00475 warn_ref_to_stack();
00476 }
00477 cr->reference();
00478 }
00479 clear();
00480 p = cr;
00481 }
00483 void check_pointer() const
00484 {
00485 if (p && p->nreference() <= 0) {
00486 warn_bad_ref_count();
00487 }
00488 }
00490 void ref_info(std::ostream& os) const
00491 {
00492 RefBase::ref_info(p,os);
00493 }
00495 void warn(const char*s) const { RefBase::warn(s); }
00496 };
00497
00498 }
00499
00500 #endif
00501
00502
00503
00504
00505
00506
00507