_handle.h

Go to the documentation of this file.
00001 /* === E T L =============================================================== */
00025 /* ========================================================================= */
00026 
00027 /* === S T A R T =========================================================== */
00028 
00029 #ifndef __ETL__HANDLE_H
00030 #define __ETL__HANDLE_H
00031 
00032 /* === H E A D E R S ======================================================= */
00033 
00034 #include <cassert>
00035 
00036 /* === M A C R O S ========================================================= */
00037 
00038 /* === T Y P E D E F S ===================================================== */
00039 
00040 #define ETL_SELF_DELETING_SHARED_OBJECT
00041 
00042 /* === C L A S S E S & S T R U C T S ======================================= */
00043 
00044 #ifdef NDEBUG
00045 #define assert_cast     static_cast
00046 #else
00047 #define assert_cast     dynamic_cast
00048 #endif
00049 
00050 
00051 _ETL_BEGIN_NAMESPACE
00052 
00053 // Forward Declarations
00054 template <class T> class handle;
00055 template <class T> class loose_handle;
00056 template <class T> class rhandle;
00057 
00058 
00059 // ========================================================================
00065 class shared_object
00066 {
00067 private:
00068     mutable int refcount;
00069 
00070 protected:
00071     shared_object():refcount(0) { }
00072 
00073 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00074     virtual ~shared_object() { }
00075 #else
00076     ~shared_object() { }
00077 #endif
00078 
00079 public:
00080     void ref()const
00081         { assert(refcount>=0); refcount++; }
00082 
00084     bool unref()const
00085     {
00086         assert(refcount>0);
00087 
00088         refcount--;
00089 
00090         if(refcount==0) {
00091 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00092             refcount=-666;
00093             delete this;
00094 #endif
00095             return false;
00096         }
00097 
00098         return true;
00099     }
00100 
00101     int count()const
00102         { return refcount; }
00103 }; // END of class shared_object
00104 
00105 // ========================================================================
00111 class virtual_shared_object
00112 {
00113 protected:
00114     virtual_shared_object() { }
00115 public:
00116     virtual ~virtual_shared_object()=0;
00117     virtual void ref()const=0;
00118     virtual bool unref()const=0;
00119     virtual int count()const=0;
00120     virtual virtual_shared_object *clone()=0;
00121 }; // END of class virtual_shared_object
00122 
00123 // ========================================================================
00129 template <class T>
00130 class handle
00131 {
00132 public:
00133 
00134     typedef T value_type;
00135     typedef T& reference;
00136     typedef const T& const_reference;
00137     typedef T* pointer;
00138     typedef const T* const_pointer;
00139     typedef int count_type;
00140     typedef int size_type;
00141 
00142 protected:
00143     value_type *obj;        
00144 
00145 public:
00146 
00148     handle():obj(NULL) {}
00149 
00151     handle(pointer x):obj(x)
00152     {
00153         if(obj)
00154             obj->ref();
00155     }
00156 
00158     handle(const handle<value_type> &x):obj(x.get())
00159     {
00160         if(obj)
00161             obj->ref();
00162     }
00163 
00165     ~handle() { detach(); }
00166 
00168 
00171     /*
00172     template <class U> handle<value_type> &
00173     operator=(const handle<U> &x)
00174     {
00175         if(x.get()==obj)
00176             return *this;
00177 
00178         detach();
00179 
00180         obj=static_cast<value_type*>(x.get());
00181         if(obj)obj->ref();
00182         return *this;
00183     }
00184     */
00185 
00187     handle<value_type> &
00188     operator=(const handle<value_type> &x)
00189     {
00190         if(x.get()==obj)
00191             return *this;
00192 
00193         detach();
00194 
00195         obj=x.get();
00196         if(obj)obj->ref();
00197         return *this;
00198     }
00199 
00201     handle<value_type> &
00202     swap(handle<value_type> &x)
00203     {
00204         pointer ptr=x.obj;
00205         x.obj=x.get();
00206         obj=ptr;
00207         return *this;
00208     }
00209 
00211 
00212     void
00213     detach()
00214     {
00215         pointer xobj(obj);
00216         obj=0;
00217 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
00218         if(xobj)
00219             xobj->unref();
00220 #else
00221         if(xobj && !xobj->unref())
00222             delete xobj;
00223 #endif
00224     }
00225 
00226     // This will be reintroduced with a new function
00227     //void release() { detach(); }
00228 
00229     void reset() { detach(); }
00230 
00231     bool empty()const { return obj==0; }
00232 
00234 
00235     void spawn() { operator=(handle(new T())); }
00236 
00237     handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
00238 
00240     handle<const value_type> constant()const { assert(obj); return *this; }
00241 
00243     count_type
00244     count()const
00245         { return obj?obj->count():0; }
00246 
00248     bool
00249     unique()const
00250         { assert(obj); return count()==1; }
00251 
00252     reference
00253     operator*()const
00254         { assert(obj); return *obj; }
00255 
00256     pointer
00257     operator->()const
00258         { assert(obj); return obj; }
00259 
00261     operator bool()const
00262         { return obj!=NULL; }
00263 
00264     operator handle<const value_type>()const
00265     { return handle<const value_type>(static_cast<const_pointer>(obj)); }
00266 
00267 
00269     template <class U> static
00270     handle<T> cast_static(const handle<U> &x)
00271     { return handle<T>(static_cast<T*>(x.get())); }
00272 
00274     template <class U> static
00275     handle<T> cast_dynamic(const handle<U> &x)
00276     { return handle<T>(dynamic_cast<T*>(x.get())); }
00277 
00279     template <class U> static
00280     handle<T> cast_const(const handle<U> &x)
00281     { return handle<T>(const_cast<T*>(x.get())); }
00282 
00284     template <class U> static
00285     handle<T> cast_reinterpret(const handle<U> &x)
00286     { return handle<T>(reinterpret_cast<T*>(x.get())); }
00287 
00288     template<class U> static handle<T> cast_static(const loose_handle<U> &x);
00289     template<class U> static handle<T> cast_dynamic(const loose_handle<U> &x);
00290     template<class U> static handle<T> cast_const(const loose_handle<U> &x);
00291     template<class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
00292 
00293     template<class U> static handle<T> cast_static(const rhandle<U> &x);
00294     template<class U> static handle<T> cast_dynamic(const rhandle<U> &x);
00295     template<class U> static handle<T> cast_const(const rhandle<U> &x);
00296     template<class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
00297 
00298     template<class U> static handle<T> cast_static(U* x);
00299     template<class U> static handle<T> cast_dynamic(U* x);
00300     template<class U> static handle<T> cast_const(U* x);
00301     template<class U> static handle<T> cast_reinterpret(U* x);
00302 
00304     pointer get()const { return obj; }
00305 
00306     bool
00307     operator!()const
00308         { return !obj; }
00309 
00311     template <class U>
00312     operator handle<U>()const
00313     { return handle<U>(static_cast<U*>(obj)); }
00314 }; // END of template class handle
00315 
00316 // ========================================================================
00322 class rshared_object : public shared_object
00323 {
00324 private:
00325     mutable int rrefcount;
00326 
00327 public:
00328     void *front_;
00329     void *back_;
00330 
00331 protected:
00332     rshared_object():rrefcount(0),front_(0),back_(0) { }
00333 
00334 public:
00335     void rref()const
00336         { rrefcount++; }
00337 
00338     void runref()const
00339     {
00340         assert(rrefcount>0);
00341         rrefcount--;
00342     }
00343 
00344     int rcount()const
00345         { return rrefcount; }
00346 }; // END of class rshared_object
00347 
00348 // ========================================================================
00354 template <class T>
00355 class rhandle : public handle<T>
00356 {
00357     friend class rshared_object;
00358 public:
00359 
00360     typedef T value_type;
00361     typedef T& reference;
00362     typedef const T& const_reference;
00363     typedef T* pointer;
00364     typedef const T* const_pointer;
00365     typedef int count_type;
00366     typedef int size_type;
00367 
00368 
00369     using handle<value_type>::count;
00370     using handle<value_type>::unique;
00371     using handle<value_type>::operator bool;
00372     using handle<value_type>::get;
00373     using handle<value_type>::operator *;
00374     using handle<value_type>::operator ->;
00375 
00376     /*
00377     operator const handle<value_type>&()const
00378     { return *this; }
00379     */
00380 
00381 private:
00382     using handle<value_type>::obj;
00383 
00384     rhandle<value_type> *prev_;
00385     rhandle<value_type> *next_;
00386 
00387     void add_to_rlist()
00388     {
00389 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00390 
00391         assert(obj);
00392         obj->rref();
00393 
00394         // If this is the first reversable handle
00395         if(!obj->front_)
00396         {
00397             obj->front_=obj->back_=this;
00398             prev_=next_=0;
00399             return;
00400         }
00401 
00402         prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
00403         next_=0;
00404         prev_->next_=this;
00405         obj->back_=this;
00406     }
00407 
00408     void del_from_rlist()
00409     {
00410 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00411         assert(obj);
00412         obj->runref();
00413 
00414         // If this is the last reversable handle
00415         if(obj->front_==obj->back_)
00416         {
00417             obj->front_=obj->back_=0;
00418             prev_=next_=0;
00419             return;
00420         }
00421 
00422         if(!prev_)
00423             obj->front_=(void*)next_;
00424         else
00425             prev_->next_=next_;
00426 
00427         if(!next_)
00428             obj->back_=(void*)prev_;
00429         else
00430             next_->prev_=prev_;
00431     }
00432 
00433 public:
00434 
00436     rhandle() {}
00437 
00439     rhandle(pointer x):handle<T>(x)
00440     {
00441 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00442         if(obj)add_to_rlist();
00443     }
00444 
00445     rhandle(const handle<value_type> &x):handle<T>(x)
00446     {
00447 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00448         if(obj)add_to_rlist();
00449     }
00450 
00452     rhandle(const rhandle<value_type> &x):handle<T>(x)
00453     {
00454 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00455         if(obj)add_to_rlist();
00456     }
00457 
00459     ~rhandle() { detach(); }
00460 
00462 
00465     /*
00466     template <class U> const handle<value_type> &
00467     operator=(const handle<U> &x)
00468     {
00469         if(x.get()==obj)
00470             return *this;
00471 
00472         detach();
00473 
00474         obj=static_cast<value_type*>(x.get());
00475         if(obj)
00476         {
00477             obj->ref();
00478             add_to_rlist();
00479         }
00480         return *this;
00481     }
00482     */
00483 
00485     rhandle<value_type> &
00486     operator=(const rhandle<value_type> &x)
00487     {
00488 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00489         if(x.get()==obj)
00490             return *this;
00491 
00492         detach();
00493 
00494         obj=x.get();
00495         if(obj)
00496         {
00497             obj->ref();
00498             add_to_rlist();
00499         }
00500         return *this;
00501     }
00502 
00503     rhandle<value_type>&
00504     operator=(const handle<value_type> &x)
00505     {
00506 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00507         if(x.get()==obj)
00508             return *this;
00509 
00510         detach();
00511 
00512         obj=x.get();
00513         if(obj)
00514         {
00515             obj->ref();
00516             add_to_rlist();
00517         }
00518         return *this;
00519     }
00520 
00521     rhandle<value_type>&
00522     operator=(value_type* x)
00523     {
00524 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00525         if(x==obj)
00526             return *this;
00527 
00528         detach();
00529 
00530         obj=x;
00531         if(obj)
00532         {
00533             obj->ref();
00534             add_to_rlist();
00535         }
00536         return *this;
00537     }
00538 
00540 
00541     void
00542     detach()
00543     {
00544 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00545         if(obj)del_from_rlist();
00546         handle<value_type>::detach();
00547         obj=0;
00548     }
00549 
00550     // This will be reintroduced with a new function
00551     //void release() { detach(); }
00552 
00553     void reset() { detach(); }
00554 
00556 
00557     void spawn() { operator=(handle<value_type>(new T())); }
00558 
00560     count_type
00561     rcount()const
00562     {
00563 //      value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00564         return obj?obj->rcount():0;
00565     }
00566 
00568     bool
00569     runique()const
00570     {
00571 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00572         assert(obj); return obj->front_==obj->back_;
00573     }
00574 
00576     int replace(const handle<value_type> &x)
00577     {
00578 //      value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
00579         assert(obj);
00580         assert(x.get()!=obj);
00581 
00582         if(x.get()==obj)
00583             return 0;
00584 
00585         rhandle<value_type> *iter;
00586         rhandle<value_type> *next;
00587 
00588         iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
00589 
00590         assert(iter);
00591 
00592         next=iter->next_;
00593 
00594         int i=0;
00595         #ifndef NDEBUG
00596         pointer obj_=obj;
00597         #endif
00598 
00599         for(;iter;iter=next,next=iter?iter->next_:0,i++)
00600         {
00601             assert(iter->get()==obj_);
00602             (*iter)=x;
00603         }
00604 
00605         assert(obj==x.get());
00606 
00607         return i;
00608     }
00609 
00611 
00612     handle<value_type> &
00613     swap(handle<value_type> &x);
00614     /*
00615     {
00616         assert(0);
00617         pointer ptr=x.obj;
00618         x.obj=x.get();
00619         obj=ptr;
00620         return *this;
00621     }
00622     */
00623 }; // END of template class rhandle
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 // ========================================================================
00637 template <class T>
00638 class loose_handle
00639 {
00640 public:
00641 
00642     typedef T value_type;
00643     typedef T& reference;
00644     typedef const T& const_reference;
00645     typedef T* pointer;
00646     typedef const T* const_pointer;
00647     typedef int count_type;
00648     typedef int size_type;
00649 
00650 protected:
00651     value_type *obj;        
00652 
00653 public:
00654 
00656     loose_handle():obj(0) {}
00657 
00659     loose_handle(pointer x):obj(x) { }
00660 
00662     loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
00663 
00664     loose_handle(const handle<value_type> &x):obj(x.get()) { }
00665 
00666     template <class U> const loose_handle<value_type> &
00667     operator=(const handle<U> &x)
00668     {
00669         if(x.get()==obj)
00670             return *this;
00671 
00672         obj=static_cast<value_type*>(x.get());
00673         return *this;
00674     }
00675 
00676     template <class U> const loose_handle<value_type> &
00677     operator=(const loose_handle<U> &x)
00678     {
00679         if(x.get()==obj)
00680             return *this;
00681 
00682         obj=static_cast<value_type*>(x.get());
00683         return *this;
00684     }
00685 
00687     const loose_handle<value_type> &
00688     operator=(const loose_handle<value_type> &x)
00689     {
00690         if(x.get()==obj)
00691             return *this;
00692 
00693         obj=x.get();
00694         return *this;
00695     }
00696 
00698     loose_handle<value_type> &
00699     swap(loose_handle<value_type> &x)
00700     {
00701         pointer ptr=x.obj;
00702         x.obj=x.get();
00703         obj=ptr;
00704         return *this;
00705     }
00706 
00708     void detach() { obj=0;  }
00709 
00710     // This will be reintroduced with a new function
00711     //void release() { detach(); }
00712 
00713     void reset() { detach(); }
00714 
00715     bool empty()const { return obj==0; }
00716 
00717     handle<value_type> clone()const { assert(obj); return obj->clone(); }
00718 
00720     loose_handle<const value_type> constant()const { return *this; }
00721 
00723     count_type
00724     count()const
00725         { return obj?obj->count():0; }
00726 
00727     reference
00728     operator*()const
00729         { assert(obj); return *obj; }
00730 
00731     pointer
00732     operator->()const
00733         { assert(obj); return obj; }
00734 
00736     //template <class U>
00737     //operator loose_handle<U>()const
00738     //{ return loose_handle<U>(static_cast<U*>(obj)); }
00739 
00741     operator loose_handle<const value_type>()const
00742     { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
00743 
00744     operator handle<value_type>()const
00745     { return handle<value_type>(obj); }
00746 
00747     operator rhandle<value_type>()const
00748     { return rhandle<value_type>(obj); }
00749 
00751     pointer get()const { return obj; }
00752 
00754     operator bool()const
00755         { return obj!=0; }
00756 
00757     bool
00758     operator!()const
00759         { return !obj; }
00760 
00761     void ref() { if(obj)obj->ref(); }
00762 
00763     bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
00764 }; // END of template class loose_handle
00765 
00766 
00767 
00768 
00769 template<class T> template<class U> handle<T>
00770 handle<T>::cast_static(const loose_handle<U> &x)
00771     { return handle<T>(static_cast<T*>(x.get())); }
00772 
00773 template <class T> template <class U> handle<T>
00774 handle<T>::cast_dynamic(const loose_handle<U> &x)
00775     { return handle<T>(dynamic_cast<T*>(x.get())); }
00776 
00777 template <class T> template <class U> handle<T>
00778 handle<T>::cast_const(const loose_handle<U> &x)
00779     { return handle<T>(const_cast<T*>(x.get())); }
00780 
00781 template <class T> template <class U> handle<T>
00782 handle<T>::cast_reinterpret(const loose_handle<U> &x)
00783     { return handle<T>(reinterpret_cast<T*>(x.get())); }
00784 
00785 
00786 
00787 template <class T> template <class U> handle<T>
00788 handle<T>::cast_static(const rhandle<U> &x)
00789     { return handle<T>(static_cast<T*>(x.get())); }
00790 
00791 template <class T> template <class U> handle<T>
00792 handle<T>::cast_dynamic(const rhandle<U> &x)
00793     { return handle<T>(dynamic_cast<T*>(x.get())); }
00794 
00795 template <class T> template <class U> handle<T>
00796 handle<T>::cast_const(const rhandle<U> &x)
00797     { return handle<T>(const_cast<T*>(x.get())); }
00798 
00799 template <class T> template <class U> handle<T>
00800 handle<T>::cast_reinterpret(const rhandle<U> &x)
00801     { return handle<T>(reinterpret_cast<T*>(x.get())); }
00802 
00803 
00804 
00805 template <class T> template <class U> handle<T>
00806 handle<T>::cast_static(U* x)
00807     { return handle<T>(static_cast<T*>(x)); }
00808 
00809 template <class T> template <class U> handle<T>
00810 handle<T>::cast_dynamic(U* x)
00811     { return handle<T>(dynamic_cast<T*>(x)); }
00812 
00813 template <class T> template <class U> handle<T>
00814 handle<T>::cast_const(U* x)
00815     { return handle<T>(const_cast<T*>(x)); }
00816 
00817 template <class T> template <class U> handle<T>
00818 handle<T>::cast_reinterpret(U* x)
00819     { return handle<T>(reinterpret_cast<T*>(x)); }
00820 
00821 
00822 
00823 
00824 
00825 template <class T,class U> bool
00826 operator==(const handle<T> &lhs,const handle<U> &rhs)
00827     { return (lhs.get()==rhs.get()); }
00828 template <class T,class U> bool
00829 operator==(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
00830     { return (lhs.get()==rhs.get()); }
00831 template <class T,class U> bool
00832 operator==(const handle<T> &lhs,const loose_handle<U> &rhs)
00833     { return (lhs.get()==rhs.get()); }
00834 template <class T,class U> bool
00835 operator==(const loose_handle<T> &lhs,const handle<U> &rhs)
00836     { return (lhs.get()==rhs.get()); }
00837 template <class T> bool
00838 operator==(const handle<T> &lhs,const T *rhs)
00839     { return (lhs.get()==rhs); }
00840 template <class T> bool
00841 operator==(const loose_handle<T> &lhs,const T *rhs)
00842     { return (lhs.get()==rhs); }
00843 template <class T> bool
00844 operator==(const T *lhs,const handle<T> &rhs)
00845     { return (lhs==rhs.get()); }
00846 template <class T> bool
00847 operator==(const T *lhs,const loose_handle<T> &rhs)
00848     { return (lhs==rhs.get()); }
00849 
00850 
00851 template <class T,class U> bool
00852 operator!=(const handle<T> &lhs,const handle<U> &rhs)
00853     { return (lhs.get()!=rhs.get()); }
00854 template <class T,class U> bool
00855 operator!=(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
00856     { return (lhs.get()!=rhs.get()); }
00857 template <class T,class U> bool
00858 operator!=(const handle<T> &lhs,const loose_handle<U> &rhs)
00859     { return (lhs.get()!=rhs.get()); }
00860 template <class T,class U> bool
00861 operator!=(const loose_handle<T> &lhs,const handle<U> &rhs)
00862     { return (lhs.get()!=rhs.get()); }
00863 template <class T> bool
00864 operator!=(const handle<T> &lhs,const T *rhs)
00865     { return (lhs.get()!=rhs); }
00866 template <class T> bool
00867 operator!=(const loose_handle<T> &lhs,const T *rhs)
00868     { return (lhs.get()!=rhs); }
00869 template <class T> bool
00870 operator!=(const T *lhs,const handle<T> &rhs)
00871     { return (lhs!=rhs.get()); }
00872 template <class T> bool
00873 operator!=(const T *lhs,const loose_handle<T> &rhs)
00874     { return (lhs!=rhs.get()); }
00875 
00876 
00877 template <class T,class U> bool
00878 operator<(const handle<T> &lhs,const handle<U> &rhs)
00879     { return (lhs.get()<rhs.get()); }
00880 template <class T,class U> bool
00881 operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
00882     { return (lhs.get()<rhs.get()); }
00883 template <class T,class U> bool
00884 operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
00885     { return (lhs.get()<rhs.get()); }
00886 template <class T,class U> bool
00887 operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
00888     { return (lhs.get()<rhs.get()); }
00889 template <class T> bool
00890 operator<(const handle<T> &lhs,const T *rhs)
00891     { return (lhs.get()<rhs); }
00892 template <class T> bool
00893 operator<(const loose_handle<T> &lhs,const T *rhs)
00894     { return (lhs.get()<rhs); }
00895 template <class T> bool
00896 operator<(const T *lhs,const handle<T> &rhs)
00897     { return (lhs<rhs.get()); }
00898 template <class T> bool
00899 operator<(const T *lhs,const loose_handle<T> &rhs)
00900     { return (lhs<rhs.get()); }
00901 
00902 _ETL_END_NAMESPACE
00903 
00904 /* === E N D =============================================================== */
00905 
00906 #endif

Generated on Fri Jun 22 14:48:47 2007 for ETL by  doxygen 1.5.2