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
#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
00214 }
00215
RefCount(
const RefCount&): _reference_count_(0) {
00216 __REF_INITLOCK__();
00217
00218 }
00219
00220
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
00362
00363
00364
00365
00366
00367
00368
00369
00370
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
00513
00514
00515