Google

Main Page   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

ref.h

00001 //
00002 // ref.h --- definitions of the reference counting classes
00003 //
00004 // Copyright (C) 1996 Limit Point Systems, Inc.
00005 //
00006 // Author: Curtis Janssen <cljanss@limitpt.com>
00007 // Maintainer: LPS
00008 //
00009 // This file is part of the SC Toolkit.
00010 //
00011 // The SC Toolkit is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Library General Public License as published by
00013 // the Free Software Foundation; either version 2, or (at your option)
00014 // any later version.
00015 //
00016 // The SC Toolkit is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU Library General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Library General Public License
00022 // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
00023 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
00024 //
00025 // The U.S. Government is granted a limited license as per AL 91-7.
00026 //
00027 
00028 //   This is the main include file for the reference counting classes.
00029 // This includes two other files: reftmpl.h and refmacr.h.  The
00030 // former is a template declaration for the reference counted classes
00031 // and the latter is generated from the former by a perl script and
00032 // provides CPP macros that declare reference counting classes.
00033 //
00034 //   The behaviour of the package can be modified with the following five
00035 // macros, each of which should be undefined, 0, or 1:
00036 //
00037 // REF_CHECK_STACK:  If this is 1 referenced objects are checked to see if they
00038 // reside on the stack, in which case storage for the object is not managed,
00039 // if management is enabled.  This feature can be confused by multiple threads
00040 // and memory checking libraries.
00041 //
00042 // REF_MANAGE:  If this is 1 the manage and unmanage members are enabled.
00043 //
00044 // REF_CHECK_MAX_NREF:  If this is 1 the reference count is checked before
00045 // it is incremented to make sure it isn't too big.
00046 //
00047 // REF_CHECK_MIN_NREF:  If this is 1 the reference count is checked before
00048 // it is decremented to make sure it isn't already zero.
00049 //
00050 // REF_USE_LOCKS:  If this is 1 then critical regions are locked before they
00051 // are entered.  This prevents erroneous behavior when multiple threads
00052 // share reference counted objects.  This will slow down certain operations,
00053 // so it should be set to 0 if your application does not need to be thread
00054 // safe.
00055 //
00056 // If a macro is undefined, then the behaviour is architecture
00057 // dependent--usually, the macro will be set to 1 in this case.
00058 // For maximum efficiency and for normal operation after the program is
00059 // debugged, compile with all of the above macros defined to zero.
00060 // This can also be done with -DREF_OPTIMIZE.
00061 //
00062 //   An include file can be used to set these options as well.  This has
00063 // the advantage that dependency checking will force an automatic
00064 // recompile of all affected files if the options change.  The file
00065 // <scconfig.h> will be include if -DHAVE_CONFIG_H is specified.
00066 //
00067 //   Note that all source code that uses references must be compiled with
00068 // the same value REF_MANAGE.  Changing this can change the storage layout
00069 // and the interpretation of the reference count data.
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         //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
00206       }
00207     RefCount(const RefCount&): _reference_count_(0) {
00208         __REF_INITLOCK__();
00209         //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
00210       }
00211 
00212     // Assigment should not overwrite the reference count.
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 //      /** Create a reference to the object a.  Do a
00354 //          dynamic_cast to convert a to the appropiate type. */
00355 //      Ref(const RefBase&a) {
00356 //          p = dynamic_cast<T*>(a.parentpointer());
00357 //          reference(p);
00358 //        }
00359 //      /** Create a reference to the object a.  Do a
00360 //          dynamic_cast to convert a to the appropiate type. */
00361 //      Ref(RefCount*a): p(0) {
00362 //        operator<<(a);
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 // Local Variables:
00505 // mode: c++
00506 // c-file-style: "CLJ"
00507 // End:

Generated at Fri Jan 10 08:14:09 2003 for MPQC 2.1.3 using the documentation package Doxygen 1.2.14.