MPQC 2.3.1
ref.h
1//
2// ref.h --- definitions of the reference counting classes
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28// This is the main include file for the reference counting classes.
29// This includes two other files: reftmpl.h and refmacr.h. The
30// former is a template declaration for the reference counted classes
31// and the latter is generated from the former by a perl script and
32// provides CPP macros that declare reference counting classes.
33//
34// The behaviour of the package can be modified with the following five
35// macros, each of which should be undefined, 0, or 1:
36//
37// REF_CHECK_STACK: If this is 1 referenced objects are checked to see if they
38// reside on the stack, in which case storage for the object is not managed,
39// if management is enabled. This feature can be confused by multiple threads
40// and memory checking libraries.
41//
42// REF_MANAGE: If this is 1 the manage and unmanage members are enabled.
43//
44// REF_CHECK_MAX_NREF: If this is 1 the reference count is checked before
45// it is incremented to make sure it isn't too big.
46//
47// REF_CHECK_MIN_NREF: If this is 1 the reference count is checked before
48// it is decremented to make sure it isn't already zero.
49//
50// REF_USE_LOCKS: If this is 1 then critical regions are locked before they
51// are entered. This prevents erroneous behavior when multiple threads
52// share reference counted objects. This will slow down certain operations,
53// so it should be set to 0 if your application does not need to be thread
54// safe.
55//
56// If a macro is undefined, then the behaviour is architecture
57// dependent--usually, the macro will be set to 1 in this case.
58// For maximum efficiency and for normal operation after the program is
59// debugged, compile with all of the above macros defined to zero.
60// This can also be done with -DREF_OPTIMIZE.
61//
62// An include file can be used to set these options as well. This has
63// the advantage that dependency checking will force an automatic
64// recompile of all affected files if the options change. The file
65// <scconfig.h> will be include if -DHAVE_CONFIG_H is specified.
66//
67// Note that all source code that uses references must be compiled with
68// the same value REF_MANAGE. Changing this can change the storage layout
69// and the interpretation of the reference count data.
70
71
72#ifdef __GNUC__
73#pragma interface
74#endif
75
76#ifndef _util_ref_ref_h
77#define _util_ref_ref_h
78
79#include <iostream>
80#include <stdlib.h>
81#include <limits.h>
82
83#include <util/ref/identity.h>
84
85#ifdef HAVE_CONFIG_H
86#include <scconfig.h>
87#endif
88
89#ifdef REF_OPTIMIZE
90#ifndef REF_CHECK_STACK
91# define REF_CHECK_STACK 0
92#endif
93#ifndef REF_MANAGE
94# define REF_MANAGE 0
95#endif
96#ifndef REF_CHECK_MAX_NREF
97# define REF_CHECK_MAX_NREF 0
98#endif
99#ifndef REF_CHECK_MIN_NREF
100# define REF_CHECK_MIN_NREF 0
101#endif
102#endif
103
104#ifdef SUNMOS
105#ifndef REF_CHECK_STACK
106#define REF_CHECK_STACK 0
107#endif
108#else
109#ifndef REF_CHECK_STACK
110#define REF_CHECK_STACK 0
111#endif
112#endif
113
114#ifndef REF_MANAGE
115#define REF_MANAGE 1
116#endif
117
118#ifndef REF_CHECK_MAX_NREF
119#define REF_CHECK_MAX_NREF 1
120#endif
121
122#ifndef REF_CHECK_MIN_NREF
123#define REF_CHECK_MIN_NREF 1
124#endif
125
126#ifndef REF_USE_LOCKS
127# if HAVE_STHREAD || HAVE_CREATETHREAD || HAVE_PTHREAD
128# define REF_USE_LOCKS 1
129# endif
130#endif
131
132#ifndef REF_ALWAYS_USE_LOCKS
133# define REF_ALWAYS_USE_LOCKS 1
134#endif
135
136#if REF_CHECK_STACK
137#include <unistd.h>
138#ifndef HAVE_SBRK_DEC
139extern "C" void * sbrk(ssize_t);
140#endif
141#define DO_REF_CHECK_STACK(p) (((void*) (p) > sbrk(0)) && (p)->managed())
142#else // REF_CHECK_STACK
143#define DO_REF_CHECK_STACK(p) (0)
144#endif // REF_CHECK_STACK
145
146#if REF_MANAGE
147#define DO_REF_UNMANAGE(p) ((p)->unmanage())
148#else // REF_MANAGE
149#define DO_REF_UNMANAGE(p)
150#endif // REF_MANAGE
151
152#if REF_USE_LOCKS
153#define __REF_LOCK__(p) p->lock_ptr()
154#define __REF_UNLOCK__(p) p->unlock_ptr()
155#if REF_ALWAYS_USE_LOCKS
156#define __REF_INITLOCK__() use_locks(true)
157#else
158#define __REF_INITLOCK__() ref_lock_ = 0xff
159#endif
160#else
161#define __REF_LOCK__(p)
162#define __REF_UNLOCK__(p)
163#define __REF_INITLOCK__()
164#endif
165
166namespace sc {
167
168typedef unsigned long refcount_t;
169
194class RefCount: public Identity {
195 private:
196#if REF_MANAGE
197# define REF_MAX_NREF (UINT_MAX - 1)
198# define REF_MANAGED_CODE UINT_MAX
199#else
200# define REF_MAX_NREF UINT_MAX
201#endif
202 unsigned int _reference_count_;
203#if REF_USE_LOCKS
204 unsigned char ref_lock_;
205#endif
206
207 void error(const char*) const;
208 void too_many_refs() const;
209 void not_enough_refs() const;
210 protected:
211 RefCount(): _reference_count_(0) {
212 __REF_INITLOCK__();
213 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
214 }
215 RefCount(const RefCount&): _reference_count_(0) {
216 __REF_INITLOCK__();
217 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
218 }
219
220 // Assigment should not overwrite the reference count.
221 RefCount& operator=(const RefCount&) { return *this; }
222 public:
223 virtual ~RefCount();
224
226 int lock_ptr() const;
228 int unlock_ptr() const;
229
231 void use_locks(bool inVal);
232
234 refcount_t nreference() const {
235# if REF_MANAGE
236 if (!managed()) return 1;
237# endif
238 return _reference_count_;
239 }
240
242 refcount_t reference() {
243# if REF_MANAGE
244 if (!managed()) return 1;
245# endif
246 __REF_LOCK__(this);
247# if REF_CHECK_MAX_NREF
248 if (_reference_count_ >= REF_MAX_NREF) too_many_refs();
249# endif
250 _reference_count_++;
251 refcount_t r = _reference_count_;
252 __REF_UNLOCK__(this);
253 return r;
254 }
255
257 refcount_t dereference() {
258# if REF_MANAGE
259 if (!managed()) return 1;
260# endif
261 __REF_LOCK__(this);
262# if REF_CHECK_MIN_NREF
263 if (_reference_count_ == 0) not_enough_refs();
264# endif
265 _reference_count_--;
266 refcount_t r = _reference_count_;
267 __REF_UNLOCK__(this);
268 return r;
269 }
270
271#if REF_MANAGE
272 int managed() const {
273 return _reference_count_ != REF_MANAGED_CODE;
274 }
280 void unmanage() {
281 _reference_count_ = REF_MANAGED_CODE;
282 }
283#else // REF_MANAGE
285 int managed() const { return 1; }
286#endif // REF_MANAGE
287};
288
292class RefBase {
293 protected:
295 void warn ( const char * msg) const;
297 void warn_ref_to_stack() const;
301 void warn_bad_ref_count() const;
303 void ref_info(RefCount*p,std::ostream& os) const;
304 void ref_info(std::ostream& os) const;
305 void check_pointer() const;
306 void reference(RefCount *);
307 int dereference(RefCount *);
308 public:
309 RefBase() {};
310 virtual ~RefBase();
312 virtual RefCount* parentpointer() const = 0;
315 void require_nonnull() const;
316};
317
331template <class T>
332class Ref : public RefBase {
333 private:
334 T* p;
335 public:
337 Ref(): p(0) {}
339 Ref(T*a) : p(0)
340 {
341 if (a) {
342 p = a;
343 reference(p);
344 }
345 }
347 Ref(const Ref<T> &a) : p(0)
348 {
349 if (a.pointer()) {
350 p = a.pointer();
351 reference(p);
352 }
353 }
355 template <class A> Ref(const Ref<A> &a): p(0)
356 {
357 if (a.pointer()) {
358 p = a.pointer();
359 reference(p);
360 }
361 }
362// /** Create a reference to the object a. Do a
363// dynamic_cast to convert a to the appropiate type. */
364// Ref(const RefBase&a) {
365// p = dynamic_cast<T*>(a.parentpointer());
366// reference(p);
367// }
368// /** Create a reference to the object a. Do a
369// dynamic_cast to convert a to the appropiate type. */
370// Ref(RefCount*a): p(0) {
371// operator<<(a);
372// }
376 {
377 clear();
378 }
381 T* operator->() const { return p; }
383 T* pointer() const { return p; }
385 RefCount *parentpointer() const { return p; }
386
387 operator T*() const { return p; }
390 T& operator *() const { return *p; };
393 int null() const { return p == 0; }
395 int nonnull() const { return p != 0; }
398 template <class A> int operator==(const Ref<A>&a) const
399 { return eq(p,a.pointer()); }
400 template <class A> int operator>=(const Ref<A>&a) const
401 { return ge(p,a.pointer()); }
402 template <class A> int operator<=(const Ref<A>&a) const
403 { return le(p,a.pointer()); }
404 template <class A> int operator>(const Ref<A>&a) const
405 { return gt(p,a.pointer()); }
406 template <class A> int operator<(const Ref<A>&a) const
407 { return lt(p,a.pointer()); }
408 template <class A> int operator!=(const Ref<A>&a) const
409 { return ne(p,a.pointer()); }
412 int compare(const Ref<T> &a) const {
413 return eq(p,a.p)?0:((lt(p,a.p)?-1:1));
414 }
416 void clear()
417 {
418 if (p) {
419 int ref = dereference(p);
420 if (ref == 0)
421 delete p;
422 p = 0;
423 }
424 }
427 {
428 T *cp = c.pointer();
429 if (cp) {
430 cp->reference();
431 clear();
432 p=cp;
433 }
434 else {
435 clear();
436 }
437 return *this;
438 }
440 template <class A> Ref<T>& operator=(const Ref<A> & c)
441 {
442 A *cp = c.pointer();
443 if (cp) {
444 cp->reference();
445 clear();
446 p=cp;
447 }
448 else {
449 clear();
450 }
451 return *this;
452 }
454 Ref<T>& operator<<(const RefBase&a) {
455 T* cr = dynamic_cast<T*>(a.parentpointer());
456 if (cr) {
457 reference(cr);
458 clear();
459 }
460 p = cr;
461 return *this;
462 }
466 Ref<T>& operator<<(RefCount *a) {
467 T* cr = dynamic_cast<T*>(a);
468 if (cr) assign_pointer(cr);
469 else if (a && a->nreference() <= 0) delete a;
470 return *this;
471 }
474 {
475 assign_pointer(cr);
476 return *this;
477 }
479 void assign_pointer(T* cr)
480 {
481 if (cr) {
482 if (DO_REF_CHECK_STACK(cr)) {
483 DO_REF_UNMANAGE(cr);
485 }
486 cr->reference();
487 }
488 clear();
489 p = cr;
490 }
492 void check_pointer() const
493 {
494 if (p && p->nreference() <= 0) {
496 }
497 }
499 void ref_info(std::ostream& os) const
500 {
501 RefBase::ref_info(p,os);
502 }
504 void warn(const char*s) const { RefBase::warn(s); }
505};
506
507}
508
509#endif
510
511// ///////////////////////////////////////////////////////////////////////////
512
513// Local Variables:
514// mode: c++
515// c-file-style: "CLJ"
516// End:
Identity gives objects a unique identity and ordering relationship relative to all other objects.
Definition: identity.h:89
Provides a few utility routines common to all Ref template instantiations.
Definition: ref.h:292
void warn_skip_stack_delete() const
Called when the deletion of stack data is skipped.
void require_nonnull() const
Requires that a nonnull reference is held.
virtual RefCount * parentpointer() const =0
Returns the DescribedClass pointer for the contained object.
void warn(const char *msg) const
Print a warning message.
void warn_ref_to_stack() const
Called when stack data is referenced.
void warn_bad_ref_count() const
Called when the reference count is corrupted.
void ref_info(RefCount *p, std::ostream &os) const
Print information about the reference.
The base class for all reference counted objects.
Definition: ref.h:194
refcount_t reference()
Increment the reference count and return the new count.
Definition: ref.h:242
int unlock_ptr() const
Unlock this object.
int lock_ptr() const
Lock this object.
refcount_t nreference() const
Return the reference count.
Definition: ref.h:234
void unmanage()
Turn off the reference counting mechanism for this object.
Definition: ref.h:280
refcount_t dereference()
Decrement the reference count and return the new count.
Definition: ref.h:257
void use_locks(bool inVal)
start and stop using locks on this object
A template class that maintains references counts.
Definition: ref.h:332
T & operator*() const
Returns a C++ reference to the reference counted object.
Definition: ref.h:390
Ref< T > & operator<<(const RefBase &a)
Assignment to the object that a references using dynamic_cast.
Definition: ref.h:454
void ref_info(std::ostream &os) const
Print information about the reference to os.
Definition: ref.h:499
Ref()
Create a reference to a null object.
Definition: ref.h:337
void assign_pointer(T *cr)
Assignment to cr.
Definition: ref.h:479
T * pointer() const
Returns a pointer the reference counted object.
Definition: ref.h:383
int null() const
Return 1 if this is a reference to a null object.
Definition: ref.h:393
RefCount * parentpointer() const
Implements the parentpointer pure virtual in the base class.
Definition: ref.h:385
Ref(const Ref< T > &a)
Create a reference to the object referred to by a.
Definition: ref.h:347
Ref(T *a)
Create a reference to the object a.
Definition: ref.h:339
Ref< T > & operator=(const Ref< T > &c)
Assignment to c.
Definition: ref.h:426
T * operator->() const
Returns the reference counted object.
Definition: ref.h:381
void clear()
Refer to the null object.
Definition: ref.h:416
int nonnull() const
Return !null().
Definition: ref.h:395
void warn(const char *s) const
Print a warning concerning the reference.
Definition: ref.h:504
void check_pointer() const
Check the validity of the pointer.
Definition: ref.h:492
~Ref()
Delete this reference to the object.
Definition: ref.h:375
int compare(const Ref< T > &a) const
Compare two objects returning -1, 0, or 1.
Definition: ref.h:412
Ref< T > & operator=(T *cr)
Assignment to cr.
Definition: ref.h:473
Ref(const Ref< A > &a)
Create a reference to the object referred to by a.
Definition: ref.h:355
int operator==(const Ref< A > &a) const
A variety of ordering and equivalence operators are provided using the Identity class.
Definition: ref.h:398

Generated at Thu Jan 19 2023 00:00:00 for MPQC 2.3.1 using the documentation package Doxygen 1.9.5.