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

ref.H

Go to the documentation of this file.
00001 /*
00002  * Copyright 1997, Brown University, Providence, RI.
00003  * 
00004  *                         All Rights Reserved
00005  * 
00006  * Permission to use, copy, modify, and distribute this software and its
00007  * documentation for any purpose other than its incorporation into a
00008  * commercial product is hereby granted without fee, provided that the
00009  * above copyright notice appear in all copies and that both that
00010  * copyright notice and this permission notice appear in supporting
00011  * documentation, and that the name of Brown University not be used in
00012  * advertising or publicity pertaining to distribution of the software
00013  * without specific, written prior permission.
00014  * 
00015  * BROWN UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00016  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
00017  * PARTICULAR PURPOSE.  IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE FOR
00018  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00019  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00020  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00021  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00022  */
00023 #ifndef REF_H_HAS_BEEN_INCLUDED
00024 #define REF_H_HAS_BEEN_INCLUDED
00025 
00026 #include <assert.h>
00027 #include "std/config.H"
00028 #include "std/thread_mutex.H"
00029 #ifdef _AIX
00030 #include <sys/atomic_op.h>
00031 #endif
00032 #ifdef sgi
00033 #include <limits.h>
00034 #include <mutex.h>
00035 #endif
00036 
00037 // AIX compiler seems to create a macro called Free(p), so this is necessary
00038 #ifdef Free
00039 #undef Free
00040 #endif
00041 
00042 #define REF_CLASS(FOO)  FOO; typedef REFptr<FOO> FOO##ptr; class FOO
00043 #define FD_REF_CLASS(FOO)  FOO; typedef REFptr<FOO> FOO##ptr
00044 // I don't think this can be replaced w/ a typedef since REFptr is typedef'd
00045 #define cREFptr const REFptr
00046 
00047 #define REF_ME(A)   ((REFcounter *)A)
00048 /*
00049 ** reference-counting base or mix-in class
00050 */
00051 
00052 class REFcounter {
00053  private:
00054    union  {
00055       struct {
00056 // Endian differences strike again
00057 // XXX - assumes WIN32 only on i386 boxes
00058 #if defined(WIN32) || defined(i386)
00059        unsigned int _ref:31;
00060        unsigned int _lock:1;
00061 #else
00062        unsigned int _lock:1;
00063        unsigned int _ref:31;
00064 #endif
00065      } _a;
00066      unsigned int _all;
00067   } _u;
00068    ThreadMutex _mutex;
00069  
00070  public:
00071             REFcounter()             { _u._all = 0; }
00072    virtual ~REFcounter()             { }
00073    void     Own()          const     {
00074 #ifdef _AIX
00075       fetch_and_add((int *) &REF_ME(this)->_u._all, 1);
00076 #elif defined(sgi)
00077       test_then_add((unsigned long *) &REF_ME(this)->_u._all, 1);
00078 #else
00079 #ifdef USE_PTHREAD
00080       CriticalSection cs((ThreadMutex*)&_mutex);
00081 #endif
00082       REF_ME(this)->_u._a._ref++;
00083 #endif
00084    }
00085             // need to lock ourself before calling delete since the destructor
00086             // may make a local REFptr to itself.  When the REFptr goes out of
00087             // scope, Free() gets called again leading to an infinite loop.
00088    void     Free()         const     {
00089       // If new value is 0...
00090 #if defined(_AIX)
00091       if (fetch_and_add((int *) &REF_ME(this)->_u._all, -1) == 1)
00092 #elif defined(sgi)
00093       // hack to do atomic decrement
00094       if (test_then_add((unsigned long *) &REF_ME(this)->_u._all, UINT_MAX)==1)
00095 #else
00096 #ifdef USE_PTHREAD
00097       CriticalSection cs((ThreadMutex*)&_mutex);
00098 #endif
00099       if (--REF_ME(this)->_u._all == 0)
00100 #endif
00101          {
00102 #if !defined(_AIX) && !defined(sgi)
00103             ((ThreadMutex*)&_mutex)->unlock();
00104 #endif
00105             REF_ME(this)->Lock();
00106 #if !defined(_AIX) && !defined(sgi)
00107             ((ThreadMutex*)&_mutex)->lock();
00108 #endif
00109             delete REF_ME(this); 
00110          }
00111    }
00112    int      Lock()                   { CriticalSection cs(&_mutex);
00113                                        int old = _u._a._lock; _u._a._lock = 1; 
00114                                        return old; }
00115    void     Unlock()                 { CriticalSection cs(&_mutex);
00116                                        _u._a._lock = 0; }
00117    int      Unique()       const     { CriticalSection cs((ThreadMutex*)&_mutex);
00118                                        return _u._a._ref == 1; }
00119 };
00120 
00121 class REFlock {
00122       REFcounter *_ref;
00123       int         _old;
00124    public :
00125       REFlock(REFcounter *r):_ref(r) { _old = _ref->Lock(); }
00126      ~REFlock()                      { if (!_old) _ref->Unlock(); }
00127 };
00128 
00129 
00130 /*
00131 ** reference-counted shared pointer
00132 */
00133 
00134 template <class T>
00135 class REFptr {
00136  protected:
00137    T * p_;
00138  public:
00139    REFptr(             ): p_(0)             { }
00140    REFptr(cREFptr<T> &p): p_(p.p_)          { if (p_) REF_ME(p_)->Own (); }
00141    REFptr(T *      pObj): p_(pObj)          { if (p_) REF_ME(p_)->Own (); }
00142 
00143    // The following should be virtual, but if so, Sun CC gives warnings about
00144    // str_ptr::operator== hiding REFptr<STR>::operator==(const REFptr<STR>&)
00145 #if !defined(sun)
00146    virtual
00147 #endif
00148    ~REFptr()                                { if (p_) REF_ME(p_)->Free(); }
00149 
00150    void      Init        ()                 { p_ = 0; }
00151    void      Clear       ()                 { if (p_) REF_ME(p_)->Free(); p_=0;}
00152 
00153    REFptr<T> &operator =  (T *      o)       { if (o    != p_) {
00154                                                  if (o) REF_ME(o)->Own(); 
00155                                                  Clear();  
00156                                                  p_ = o; 
00157                                               }    
00158                                               return *this; }
00159    REFptr<T> &operator =  (cREFptr<T>& p)    { if (p.p_ != p_) {
00160                                                  if (p.p_) REF_ME(p.p_)->Own();
00161                                                  Clear();  
00162                                                  p_ = p.p_; 
00163                                               } 
00164                                               return *this; }
00165 
00166    bool      operator == (cREFptr<T>& p) const {           return  p.p_ == p_; }
00167    bool      operator != (cREFptr<T>& p) const {           return  p.p_ != p_; }
00168 
00169    int       operator !  ()              const {           return !p_; }
00170 
00171    const T & operator *  ()              const { assert(p_);  return *p_; }
00172          T & operator *  ()                    { assert(p_);  return *p_; }
00173    const T * operator -> ()              const { assert(p_);  return  p_; }
00174          T * operator -> ()                    { assert(p_);  return  p_; }
00175 
00176              operator int()              const {              return  (int)p_;}
00177    T         *pointer()                  const { return p_; }
00178    T         *&pointer()                       { return p_; }
00179 
00180    REFptr<T> &Cast_from_void(void *V)        { *this = (T *) V; return *this; }
00181    friend ostream& operator<<(ostream& os,cREFptr<T>& p) { return os << p.p_; }
00182 };
00183 
00184 #undef REF_ME
00185 
00186 
00187 
00188 // This macro makes a REFptr baseclass that other
00189 // REFptr templates can subclass from.  The key to 
00190 // allowing subclassing is the definition of the subc
00191 // class which defines a virtual cast function.  The
00192 // derived REFptr classes will have to define a subclass
00193 // of the subc class and fill in the cast function with
00194 // something that can return the subclass type.
00195 //
00196 #define MAKE_PTR_BASEC(A)             \
00197 class A;                              \
00198 class A##subc {                       \
00199    public :                           \
00200       virtual A *A##cast() const = 0; \
00201 };                                    \
00202 typedef const class A##ptr c##A##ptr; \
00203 class A##ptr : public REFptr<A>, public A##subc {  \
00204    public :                                        \
00205      A##ptr()                                   { }\
00206      A##ptr(A             *g): REFptr<A>(g)     { }\
00207      A##ptr(const A##ptr  &p): REFptr<A>(p.p_)  { }\
00208      A##ptr(const A##subc &p): REFptr<A>(p.A##cast()) { } \
00209                                                    \
00210     virtual A *A##cast() const { return p_; } \
00211 }
00212 
00213 
00214 // this macro is used to define a REFptr subclass from another
00215 // templated REFptr.  We can't use normal inheritance because
00216 // we want the subclassed pointer to return different template
00217 // types than the parent pointer for all of the derefrencing
00218 // functions.  Thus we define the subclass pointer to multiply
00219 // inherit from its template defintion and from a "hack" subc
00220 // class for the parent.  In addition, this macro defines a
00221 // "hack" subc class for the subclassed pointer so that other
00222 // ptr classes can in turn subclass from it.
00223 //
00224 #define MAKE_PTR_SUBC(A,B) \
00225 class A; \
00226 class A##subc: public B##subc  {  \
00227    public :  \
00228       virtual A *A##cast() const = 0; \
00229       virtual B *B##cast() const { return (B *)A##cast(); } \
00230 }; \
00231 typedef const class A##ptr c##A##ptr; \
00232 class A##ptr : public REFptr<A>, public A##subc {  \
00233    public :                                        \
00234      A##ptr()                                   { }\
00235      A##ptr(A             *g): REFptr<A>(g)     { }\
00236      A##ptr(const A##ptr  &p): REFptr<A>(p.p_)  { }\
00237      A##ptr(const A##subc &p): REFptr<A>(p.A##cast()) { } \
00238                                                    \
00239     virtual A *A##cast() const { return p_; } \
00240 }
00241 
00242 #endif // REF_H_HAS_BEEN_INCLUDED

Generated on Mon Sep 15 16:25:57 2003 for gluebase by doxygen1.2.18