Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members

referencecounted.h

00001 /***************************************************************************
00002                           referencecounted.h  -  description
00003                              -------------------
00004     begin                : Sat Aug 2 2003
00005     copyright            : (C) 2003 by Jacques Gasselin de Richebourg
00006     email                : jacquesgasselin@hotmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU Lesser General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #ifndef REFERENCECOUNTED_H
00019 #define REFERENCECOUNTED_H
00020 
00021 
00022 #include <map>
00023 #include <iostream>
00024 #include <string>
00025 
00026 #include "glassert.h"
00027 
00028 
00033 class ReferenceCounted
00034 {
00035    int count;
00036    //if count == 0 it should be deleted
00037    
00038    public:
00039 
00040    ReferenceCounted():count(0){}
00041    ReferenceCounted( const ReferenceCounted& ):count(0){}
00042 
00043    virtual ~ReferenceCounted(){}
00044 
00045    inline void ref() { ++count; }
00046    inline ReferenceCounted* unref()
00047    {
00048       --count;
00049       if(count < 1)
00050       {  delete this; return NULL; }
00051       return this;
00052    }
00053 
00054    inline int getCount() { return count; }
00055 };
00056 
00060 template <class T>
00061 class IRCPointer
00062 {
00063 public:
00064    ReferenceCounted* rc;
00065 
00066    IRCPointer()
00067    :rc(NULL) {}
00068 
00069    IRCPointer(const IRCPointer& irc)
00070    :rc(irc.rc) { ref(); }
00071 
00072    template<class T2>
00073    IRCPointer(const IRCPointer<T2>& irc)
00074    :rc(irc.rc) { ref(); }
00075 
00076    IRCPointer( T* p )
00077    :rc(NULL)
00078    {
00079       rc = p;
00080       ref();
00081    }
00082    
00083    ~IRCPointer()
00084    { unref(); }
00085 
00086    IRCPointer& operator = (const IRCPointer& irc)
00087    { irc.ref(); unref(); rc = irc.rc; return *this; }
00088 
00089    template<class T2>
00090    IRCPointer& operator = (const IRCPointer<T2>& irc)
00091    { irc.ref(); unref(); rc = irc.rc; return *this; }
00092 
00093    IRCPointer& operator = (T* p)
00094    { if(p) p->ref(); unref(); rc = p; return *this; }
00095    
00096    inline bool operator == (T* p)
00097    { return ((static_cast<ReferenceCounted*>(p) == rc) ? true : false ); }
00098 
00099    inline bool operator != (T* p)
00100    { return ((static_cast<ReferenceCounted*>(p) != rc) ? true : false ); }
00101 
00102    inline operator T* (void)
00103    { return static_cast<T*>(rc); }
00104    
00105    inline T* operator ->(void)
00106    { return static_cast<T*>(rc); }
00107 
00108    T& operator *(void)
00109    { return *(static_cast<T*>(rc)); }
00110    
00111    inline void ref(void) const
00112    {
00113       if( rc )
00114          rc->ref();
00115    }
00116       
00117    inline void unref(void)
00118    {
00119       if( rc )
00120          rc = rc->unref();
00121    }
00122 };
00123 
00124 
00126 template <class T, bool HasArray = false, class R = T>
00127 class RCPointer
00128 {
00129 protected:
00130    typedef std::pair<int, void*> pairType;
00131    pairType* countedPointer;
00132 
00133 public:
00134 
00135    RCPointer();
00136    RCPointer(T*);
00137    RCPointer(const RCPointer&);
00138    template <class T2>
00139    RCPointer(const RCPointer<T2, HasArray, T2>&);
00140 
00141    ~RCPointer();
00142 
00143    RCPointer& operator = (const RCPointer&);
00144 
00145    template <class T2>
00146    RCPointer& operator = (const RCPointer<T2, HasArray, T2>&);
00147 
00148    RCPointer& operator = (T* p)
00149    {
00150       PRINT(typeid(this).name()<<"::operator = ("<<p<<") used")
00151       if(countedPointer)
00152       {
00153          if(p != countedPointer->second)
00154             unref();        //not a reused pointer
00155          else
00156             return *this;
00157       }
00158 
00159       countedPointer = new pairType(1,p);
00160       return *this;
00161    }
00162 
00163    inline bool operator == (T*);
00164    inline bool operator != (T*);
00165 
00166 
00167    inline operator T* (void);
00168    inline T* operator ->(void);
00169    T& operator *(void);
00170    R& operator [](const int);
00171 
00172    inline void ref(void) const;
00173    inline void unref(void);
00174 
00175    inline pairType* getCountedPointer() const { return countedPointer; }
00176 };
00177 
00179 template <class T, bool HasArray, class R>
00180 RCPointer<T,HasArray,R>::RCPointer()
00181 :countedPointer(NULL)
00182 {
00183    PRINT(typeid(this).name()<<" created with no countedPointer ");
00184 }
00185 
00186 template <class T, bool HasArray, class R>
00187 RCPointer<T,HasArray,R>::RCPointer(T* p)
00188 :countedPointer(NULL)
00189 {
00190    if(p)
00191    {
00192       countedPointer = new pairType(1,p);
00193       PRINT(typeid(this).name()<<" created with count: "<<countedPointer->first);
00194    }
00195 }
00196 
00197 template <class T, bool HasArray, class R>
00198 RCPointer<T,HasArray,R>::RCPointer(const RCPointer& rc)
00199 :countedPointer(NULL)
00200 {
00201 
00202    PRINT(typeid(this).name()<<" copied ");
00203    if( &rc )
00204    {
00205       countedPointer = rc.countedPointer;
00206 
00207       ref();
00208    }
00209 }
00210 
00211 template <class T, bool HasArray, class R>
00212 template <class T2>
00213 RCPointer<T,HasArray,R>::RCPointer(const RCPointer<T2, HasArray, T2>& rc)
00214 :countedPointer(NULL)
00215 {
00216 
00217    PRINT(typeid(this).name()<<" copied from "<<typeid(&rc).name())
00218 
00219    if( &rc )
00220    {
00221       if( rc.getCountedPointer() )
00222       {
00223          countedPointer = rc.getCountedPointer();
00224          ref();
00225       }
00226    }
00227 }
00228 
00229 template <class T, bool HasArray, class R>
00230 RCPointer<T,HasArray,R>::~RCPointer()
00231 {
00232    if(countedPointer)
00233    {
00234       PRINT(typeid(this).name()<<" attempted deletion at count: "<<countedPointer->first -1);
00235       unref();
00236    }
00237 }
00238 
00239 template <class T, bool HasArray, class R>
00240 RCPointer<T,HasArray,R>& RCPointer<T,HasArray,R>::operator = (const RCPointer<T,HasArray,R>& rc)
00241 {
00242    PRINT(typeid(this).name()<<"::operator = ("<<typeid(this).name()<<") used")
00243 
00244    rc.ref();
00245 
00246    unref();
00247 
00248    countedPointer = rc.countedPointer;
00249 
00250    return *this;
00251 }
00252 
00253 template <class T, bool HasArray, class R>
00254 template <class T2>
00255 RCPointer<T,HasArray,R>& RCPointer<T,HasArray,R>::operator = (const RCPointer<T2, HasArray, T2>& rc)
00256 {
00257    PRINT(typeid(this).name()<<"::operator = ("<<typeid(&rc).name()<<") used")
00258 
00259    rc.ref();
00260 
00261    unref();
00262 
00263    countedPointer = rc.getCountedPointer();
00264 
00265    if( dynamic_cast<T*>( static_cast<T2*>(countedPointer->second) ) )
00266    {// casting is possible
00267 
00268    }
00269    else
00270    {
00271       unref();
00272    }
00273 
00274    return *this;
00275 }
00276 
00277 template <class T, bool HasArray, class R>
00278 bool RCPointer<T,HasArray,R>::operator == (T* p)
00279 {
00280    PRINT(typeid(this).name()<<"::operator == ("<<p<<") used")
00281 
00282    if(countedPointer)
00283    {
00284       if(countedPointer->second == p)
00285          return true;
00286       else
00287          return false;
00288    }
00289    else
00290    {
00291       if(p == NULL)
00292          return true;
00293       else
00294          return false;
00295    }
00296 }
00297 
00298 template <class T, bool HasArray, class R>
00299 bool RCPointer<T,HasArray,R>::operator != (T* p)
00300 {
00301    PRINT(typeid(this).name()<<"::operator != ("<<p<<") used")
00302 
00303    if(countedPointer)
00304    {
00305       if(p != countedPointer->second)
00306          return true;
00307       else
00308          return false;
00309    }
00310    else
00311    {
00312       if(p == NULL)
00313          return false;
00314       else
00315          return true;
00316    }
00317 }
00318 
00319 template <class T, bool HasArray, class R>
00320 RCPointer<T,HasArray,R>::operator T* (void)
00321 {
00322    PRINT(typeid(this).name()<<"::operator (T*) () used")
00323    if(countedPointer)
00324       return static_cast<T*>(countedPointer->second);
00325    else
00326       return NULL;
00327 }
00328 
00329 template <class T, bool HasArray, class R>
00330 inline T* RCPointer<T,HasArray,R>::operator ->(void)
00331 {
00332    PRINT(typeid(this).name()<<"::operator -> () used")
00333    if(countedPointer)
00334       return static_cast<T*>(countedPointer->second);
00335    else
00336       return NULL;
00337 }
00338 
00339 template <class T, bool HasArray, class R>
00340 T& RCPointer<T,HasArray,R>::operator *(void)
00341 {
00342    PRINT(typeid(this).name()<<"::operator * () used")
00343 
00344    customAssert(countedPointer, "no valid pointer in T& op * from RCP");
00345 
00346    return *(static_cast<T*>(countedPointer->second));
00347 }
00348 
00349 template <class T, bool HasArray, class R>
00350 R& RCPointer<T,HasArray,R>::operator [](const int index)
00351 {
00352    PRINT(typeid(this).name()<<"::operator [] ("<<index<<") used")
00353 
00354    customAssert(countedPointer, "no valid pointer in R& op [] from RCP");
00355 
00356    return (static_cast<T*>(countedPointer->second)) [index];
00357 }
00358 
00359 template <class T, bool HasArray, class R>
00360 void RCPointer<T,HasArray,R>::ref (void) const
00361 {
00362    PRINT(typeid(this).name()<<" ref used")
00363 
00364    if(countedPointer)
00365       ++(countedPointer->first); //reference pointer
00366 }
00367 
00368 template <class T, bool HasArray, class R>
00369 void RCPointer<T,HasArray,R>::unref (void)
00370 {
00371    PRINT(typeid(this).name()<<" unref used")
00372 
00373    if(countedPointer)
00374    {
00375       --(countedPointer->first); //unreference pointer
00376 
00377       if(countedPointer->first < 1)
00378       {//last reference expired
00379          PRINT(typeid(this).name()<<" has gone out of reference, is deleted by default.")
00380          if(countedPointer->second)
00381          {
00382             if(HasArray)
00383                delete [] (static_cast<T*>(countedPointer->second));
00384             else
00385                delete (static_cast<T*>(countedPointer->second));
00386          }
00387 
00388          delete countedPointer;
00389       }
00390 
00391       countedPointer = NULL;
00392       
00393       //else someone else is referencing the pointer
00394       //not ready to be deleted
00395    }
00396 }
00397 
00398 
00399 #endif

Generated on Wed Feb 4 23:11:34 2004 by doxygen 1.3.3