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
139 extern "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 
166 namespace sc {
167 
168 typedef unsigned long refcount_t;
169 
194 class 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
284  int managed() const { return 1; }
286 #endif // REF_MANAGE
287 };
288 
292 class RefBase {
293  protected:
295  void warn ( const char * msg) const;
297  void warn_ref_to_stack() const;
299  void warn_skip_stack_delete() 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 
331 template <class T>
332 class 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  }
426  Ref<T>& operator=(const Ref<T> & c)
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  }
455  T* cr = dynamic_cast<T*>(a.parentpointer());
456  if (cr) {
457  reference(cr);
458  clear();
459  }
460  p = cr;
461  return *this;
462  }
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:
sc::Identity
Identity gives objects a unique identity and ordering relationship relative to all other objects.
Definition: identity.h:89
sc::RefBase::warn_bad_ref_count
void warn_bad_ref_count() const
Called when the reference count is corrupted.
sc::Ref::operator==
int operator==(const Ref< A > &a) const
A variety of ordering and equivalence operators are provided using the Identity class.
Definition: ref.h:398
sc::RefBase::warn_ref_to_stack
void warn_ref_to_stack() const
Called when stack data is referenced.
sc::Ref::compare
int compare(const Ref< T > &a) const
Compare two objects returning -1, 0, or 1.
Definition: ref.h:412
sc::RefBase::warn_skip_stack_delete
void warn_skip_stack_delete() const
Called when the deletion of stack data is skipped.
sc::Ref
A template class that maintains references counts.
Definition: ref.h:332
sc::Ref::Ref
Ref(const Ref< T > &a)
Create a reference to the object referred to by a.
Definition: ref.h:347
sc::Ref::Ref
Ref(const Ref< A > &a)
Create a reference to the object referred to by a.
Definition: ref.h:355
sc::Ref::operator<<
Ref< T > & operator<<(const RefBase &a)
Assignment to the object that a references using dynamic_cast.
Definition: ref.h:454
sc::Ref::operator=
Ref< T > & operator=(T *cr)
Assignment to cr.
Definition: ref.h:473
sc::Ref::pointer
T * pointer() const
Returns a pointer the reference counted object.
Definition: ref.h:383
sc::Ref::operator->
T * operator->() const
Returns the reference counted object.
Definition: ref.h:381
sc::Ref::operator*
T & operator*() const
Returns a C++ reference to the reference counted object.
Definition: ref.h:390
sc::Ref::clear
void clear()
Refer to the null object.
Definition: ref.h:416
sc::RefBase
Provides a few utility routines common to all Ref template instantiations.
Definition: ref.h:292
sc::RefCount::unlock_ptr
int unlock_ptr() const
Unlock this object.
sc::RefBase::ref_info
void ref_info(RefCount *p, std::ostream &os) const
Print information about the reference.
sc::RefCount::nreference
refcount_t nreference() const
Return the reference count.
Definition: ref.h:234
sc::Ref::Ref
Ref(T *a)
Create a reference to the object a.
Definition: ref.h:339
sc::RefCount::lock_ptr
int lock_ptr() const
Lock this object.
sc::Ref::assign_pointer
void assign_pointer(T *cr)
Assignment to cr.
Definition: ref.h:479
sc::RefCount::unmanage
void unmanage()
Turn off the reference counting mechanism for this object.
Definition: ref.h:280
sc::RefBase::parentpointer
virtual RefCount * parentpointer() const =0
Returns the DescribedClass pointer for the contained object.
sc::RefCount::dereference
refcount_t dereference()
Decrement the reference count and return the new count.
Definition: ref.h:257
sc::RefBase::require_nonnull
void require_nonnull() const
Requires that a nonnull reference is held.
sc::RefCount::use_locks
void use_locks(bool inVal)
start and stop using locks on this object
sc::Ref::Ref
Ref()
Create a reference to a null object.
Definition: ref.h:337
sc::Ref::~Ref
~Ref()
Create a reference to the object a.
Definition: ref.h:375
sc::Ref::ref_info
void ref_info(std::ostream &os) const
Print information about the reference to os.
Definition: ref.h:499
sc::Ref::operator=
Ref< T > & operator=(const Ref< A > &c)
Assignment to c.
Definition: ref.h:440
sc::Ref::nonnull
int nonnull() const
Return !null().
Definition: ref.h:395
sc::Ref::warn
void warn(const char *s) const
Print a warning concerning the reference.
Definition: ref.h:504
sc::RefCount
The base class for all reference counted objects.
Definition: ref.h:194
sc::Ref::check_pointer
void check_pointer() const
Check the validity of the pointer.
Definition: ref.h:492
sc::Ref::operator=
Ref< T > & operator=(const Ref< T > &c)
Assignment to c.
Definition: ref.h:426
sc::RefBase::warn
void warn(const char *msg) const
Print a warning message.
sc::Ref::parentpointer
RefCount * parentpointer() const
Implements the parentpointer pure virtual in the base class.
Definition: ref.h:385
sc::RefCount::reference
refcount_t reference()
Increment the reference count and return the new count.
Definition: ref.h:242

Generated at Sun Jan 26 2020 23:33:04 for MPQC 2.3.1 using the documentation package Doxygen 1.8.16.