Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ref.H

Go to the documentation of this file.
00001 #ifndef REF_H_HAS_BEEN_INCLUDED
00002 #define REF_H_HAS_BEEN_INCLUDED
00003 
00004 #include <cassert>
00005 
00006 #include "std/iostream.H"
00007 
00008 #include "platform.H"
00009 #include "thread_mutex.H"
00010 
00011 #ifdef _AIX
00012 #include <sys/atomic_op.h>
00013 #endif
00014 
00015 #ifdef sgi
00016 #include <climits>
00017 #include <mutex.h>
00018 #endif
00019 
00020 // AIX compiler seems to create a macro called Free(p), so this is necessary
00021 #ifdef Free
00022 #undef Free
00023 #endif
00024 
00025 #define CREFptr const REFptr
00026 #define REF_ME(A)   ((REFcounter *)A)
00027 
00028 /*****************************************************************
00029  * REFcounter:
00030  *
00031  *   Reference-counting base or mix-in class.
00032  *
00033  *   I.e., A class that wants to be ref-counted derives from this.
00034  *****************************************************************/
00035 class REFcounter {
00036  private:
00037 
00038    union  {
00039       struct {
00040 // Endian differences strike again
00041 // XXX - assumes WIN32 only on i386 boxes
00042 #if defined(WIN32) || defined(i386)
00043          unsigned int _ref:31;
00044          unsigned int _lock:1;
00045 #else
00046          unsigned int _lock:1;
00047          unsigned int _ref:31;
00048 #endif
00049       } _a;
00050       unsigned int _all;
00051    } _u;
00052 
00053    ThreadMutex _mutex;
00054  
00055  public:
00056    REFcounter() { _u._all = 0; }
00057    virtual ~REFcounter() {}
00058 
00059    void     Own() const {
00060 #ifdef _AIX
00061       fetch_and_add((int *) &REF_ME(this)->_u._all, 1);
00062 #elif defined(sgi)
00063       test_then_add((unsigned long *) &REF_ME(this)->_u._all, 1);
00064 #else
00065 #ifdef USE_PTHREAD
00066       CriticalSection cs((ThreadMutex*)&_mutex);
00067 #endif
00068       REF_ME(this)->_u._a._ref++;
00069 #endif
00070    }
00071 
00072    // Need to lock ourself before calling delete since the
00073    // destructor may make a local REFptr to itself.  When the
00074    // REFptr goes out of scope, Free() gets called again leading
00075    // to an infinite loop.
00076    void     Free()         const     {
00077    //This chunk of code is just the conditional if the IF statement
00078       // If new value is 0...
00079 #if defined(_AIX)
00080       if ( fetch_and_add((int *) &REF_ME(this)->_u._all, -1) == 1 )
00081 #elif defined(sgi)
00082       // hack to do atomic decrement
00083       if ( test_then_add((unsigned long *) &REF_ME(this)->_u._all, UINT_MAX)==1 )
00084 #else
00085 #ifdef USE_PTHREAD
00086       CriticalSection cs((ThreadMutex*)&_mutex);
00087 #endif
00088       if (--REF_ME(this)->_u._all == 0)
00089 #endif
00090      // THEN
00091          {
00092 #if !defined(_AIX) && !defined(sgi)
00093             ((ThreadMutex*)&_mutex)->unlock();
00094 #endif
00095             REF_ME(this)->Lock();
00096 #if !defined(_AIX) && !defined(sgi)
00097             ((ThreadMutex*)&_mutex)->lock();
00098 #endif
00099             delete REF_ME(this); 
00100          }
00101     // end crazy IF statement
00102    }
00103 
00104 
00105    int Lock() {
00106       CriticalSection cs(&_mutex);
00107       int old = _u._a._lock;
00108       _u._a._lock = 1; 
00109       return old;
00110    }
00111    void Unlock() {
00112       CriticalSection cs(&_mutex);
00113       _u._a._lock = 0;
00114    }
00115    int Unique() const {
00116       CriticalSection cs((ThreadMutex*)&_mutex);
00117       return _u._a._ref == 1;
00118    }
00119 };
00120 
00121 /*****************************************************************
00122  * REFlock:
00123  *
00124  *   Temporarily locks a REFcounter so it won't delete its
00125  *   pointer when the number of owners hits zero.
00126  *****************************************************************/
00127 class REFlock {
00128    REFcounter*  _ref;
00129    int          _old;
00130  public :
00131    REFlock(REFcounter *r):_ref(r)  { _old = _ref->Lock(); }
00132    ~REFlock()                      { if (!_old) _ref->Unlock(); }
00133 };
00134 
00135 /*****************************************************************
00136  * REFptr:
00137  *
00138  *   Reference-counted shared pointer. Wraps around the "real"
00139  *   pointer, which points to an object derived from REFcounter.
00140  *   I.e., the REFcounter object has the count of its owners
00141  *   in its own data.
00142  *****************************************************************/
00143 template <class T>
00144 class REFptr {
00145  protected:
00146    T*    p_;    // The real pointer
00147 
00148  public:
00149    //******** MANAGERS ********
00150    REFptr(             ): p_(0)             { }
00151    REFptr(CREFptr<T> &p): p_(p.p_)          { if (p_) REF_ME(p_)->Own (); }
00152    REFptr(T *      pObj): p_(pObj)          { if (p_) REF_ME(p_)->Own (); }
00153 
00154    // The following should be virtual, but if so, Sun CC
00155    // gives warnings about str_ptr::operator== hiding
00156    // REFptr<STR>::operator==(const REFptr<STR>&)
00157 #if !defined(sun)
00158    virtual
00159 #endif
00160    ~REFptr()    { if (p_) REF_ME(p_)->Free(); }
00161 
00162    void Init()  { p_ = 0; }
00163    void Clear() { if (p_) REF_ME(p_)->Free(); p_=0; }
00164 
00165    //******** ASSIGNMENT ********
00166    REFptr<T> &operator=(T* o) {
00167       if (o != p_) {
00168          if (o)
00169             REF_ME(o)->Own(); 
00170          Clear();  
00171          p_ = o; 
00172       }    
00173       return *this;
00174    }
00175    REFptr<T> &operator=(CREFptr<T>& p) {
00176       if (p.p_ != p_) {
00177          if (p.p_)
00178             REF_ME(p.p_)->Own();
00179          Clear();  
00180          p_ = p.p_; 
00181       } 
00182       return *this;
00183    }
00184 
00185    //******** EQUALITY ********
00186    bool operator == (CREFptr<T>& p)     const   { return  p.p_ == p_; }
00187    bool operator == (T* p)              const   { return     p == p_; }
00188    bool operator != (CREFptr<T>& p)     const   { return  p.p_ != p_; }
00189    bool operator != (T* p)              const   { return     p != p_; }
00190    bool operator!()                     const   { return !p_; }
00191 
00192    //******** CASTING ********
00193    const T& operator*()                 const   { assert(p_);  return *p_; }
00194    T&       operator*()                         { assert(p_);  return *p_; }
00195    const T* operator->()                const   { assert(p_);  return  p_; }
00196    T*       operator->()                        { assert(p_);  return  p_; }
00197 
00198    operator T* ()                       const   { return  p_; }
00199 
00200    REFptr<T> &Cast_from_void(void *V) { *this = (T*) V; return *this;}
00201 
00202    //******** I/0 ********
00203    friend inline ostream& operator<<(ostream& os,CREFptr<T>& p) {
00204       return os<<p.p_;
00205    }
00206 };
00207 
00208 #undef REF_ME
00209 
00210 // This macro makes a REFptr baseclass that other
00211 // REFptr templates can subclass from.  The key to 
00212 // allowing subclassing is the definition of the subc
00213 // class which defines a virtual cast function.  The
00214 // derived REFptr classes will have to define a subclass
00215 // of the subc class and fill in the cast function with
00216 // something that can return the subclass type.
00217 //
00218 #define MAKE_PTR_BASEC(A)             \
00219 class A;                              \
00220 class A##subc {                       \
00221    public :                           \
00222       virtual ~A##subc() {}           \
00223       virtual A *A##cast() const = 0; \
00224 };                                    \
00225 class A##ptr : public REFptr<A>, public A##subc {  \
00226    public :                                        \
00227      A##ptr()                                   { }\
00228      A##ptr(A             *g): REFptr<A>(g)     { }\
00229      A##ptr(const A##ptr  &p): REFptr<A>(p.p_)  { }\
00230      A##ptr(const A##subc &p): REFptr<A>(p.A##cast()) { } \
00231                                                    \
00232     virtual A *A##cast() const { return (A *)p_; } \
00233 }
00234 
00235 
00236 // This macro is used to define a REFptr subclass from another
00237 // templated REFptr.  We can't use normal inheritance because
00238 // we want the subclassed pointer to return different template
00239 // types than the parent pointer for all of the derefrencing
00240 // functions.  Thus we define the subclass pointer to multiply
00241 // inherit from its template defintion and from a "hack" subc
00242 // class for the parent.  In addition, this macro defines a
00243 // "hack" subc class for the subclassed pointer so that other
00244 // ptr classes can in turn subclass from it.
00245 //
00246 #define MAKE_PTR_SUBC(A,B) \
00247 class A; \
00248 class A##subc: public B##subc  {  \
00249    public :  \
00250       virtual A *A##cast() const = 0; \
00251       virtual B *B##cast() const { return (B *)A##cast(); } \
00252 }; \
00253 class A##ptr : public REFptr<A>, public A##subc {  \
00254    public :                                        \
00255      A##ptr()                                   { }\
00256      A##ptr(A             *g): REFptr<A>(g)     { }\
00257      A##ptr(const A##ptr  &p): REFptr<A>(p.p_)  { }\
00258      A##ptr(const A##subc &p): REFptr<A>(p.A##cast()) { } \
00259                                                    \
00260     virtual A *A##cast() const { return (A *)p_; } \
00261 }
00262 
00263 #endif // REF_H_HAS_BEEN_INCLUDED
00264 
00265 /* end of file ref.H */

Generated on Mon Sep 18 11:39:33 2006 for jot by  doxygen 1.4.4