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: