1 /* === E T L =============================================================== */
3 ** $Id: _handle.h,v 1.1.1.1 2005/01/04 01:31:47 darco Exp $
4 ** \brief Template Object Handle Implementation
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
22 ** This is an internal header file, included by other ETL headers.
23 ** You should not attempt to use it directly.
25 /* ========================================================================= */
27 /* === S T A R T =========================================================== */
29 #ifndef __ETL__HANDLE_H
30 #define __ETL__HANDLE_H
32 /* === H E A D E R S ======================================================= */
36 /* === M A C R O S ========================================================= */
38 /* === T Y P E D E F S ===================================================== */
40 #define ETL_SELF_DELETING_SHARED_OBJECT
42 /* === C L A S S E S & S T R U C T S ======================================= */
45 #define assert_cast static_cast
47 #define assert_cast dynamic_cast
53 // Forward Declarations
54 template <class T> class handle;
55 template <class T> class loose_handle;
56 template <class T> class rhandle;
59 // ========================================================================
60 /*! \class shared_object _handle.h ETL/handle
61 ** \brief Shared Object Base Class
62 ** \see handle, loose_handle
71 shared_object():refcount(0) { }
73 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
74 virtual ~shared_object() { }
81 { assert(refcount>=0); refcount++; }
83 //! Returns \c false if object needs to be deleted
91 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
103 }; // END of class shared_object
105 // ========================================================================
106 /*! \class virtual_shared_object _handle.h ETL/handle
107 ** \brief Virtual Shared Object Base Class
108 ** \see handle, loose_handle
111 class virtual_shared_object
114 virtual_shared_object() { }
116 virtual ~virtual_shared_object()=0;
117 virtual void ref()const=0;
118 virtual bool unref()const=0;
119 virtual int count()const=0;
120 virtual virtual_shared_object *clone()=0;
121 }; // END of class virtual_shared_object
123 // ========================================================================
124 /*! \class handle _handle.h ETL/handle
125 ** \brief Object Handle
126 ** \see shared_object, loose_handle
134 typedef T value_type;
135 typedef T& reference;
136 typedef const T& const_reference;
138 typedef const T* const_pointer;
139 typedef int count_type;
140 typedef int size_type;
143 value_type *obj; //!< Pointer to object
147 //! Default constructor - empty handle
148 handle():obj(NULL) {}
150 //! Constructor that constructs from a pointer to new object
151 handle(pointer x):obj(x)
157 //! Default copy constructor
158 handle(const handle<value_type> &x):obj(x.get())
164 //! Handle is released on deletion
165 ~handle() { detach(); }
167 //! Template Assignment operator
168 /*! \note This class may not be necessary, and may be removed
169 ** at some point in the future.
172 template <class U> handle<value_type> &
173 operator=(const handle<U> &x)
180 obj=static_cast<value_type*>(x.get());
186 //! Assignment operator
188 operator=(const handle<value_type> &x)
200 //! Swaps the values of two handles without reference counts
202 swap(handle<value_type> &x)
210 //! Handle detach procedure
211 /*! unref()'s the object and sets the internal object pointer to \c NULL */
217 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
221 if(xobj && !xobj->unref())
226 // This will be reintroduced with a new function
227 //void release() { detach(); }
229 void reset() { detach(); }
231 bool empty()const { return obj==0; }
233 //! Creates a new instance of a T object and puts it in the handle.
234 /*! Uses the default constructor */
235 void spawn() { operator=(handle(new T())); }
237 handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
239 //! Returns a constant handle to our object
240 handle<const value_type> constant()const { assert(obj); return *this; }
242 //! Returns number of instances
245 { return obj?obj->count():0; }
247 //! Returns true if there is only one instance of the object
250 { assert(obj); return count()==1; }
254 { assert(obj); return *obj; }
258 { assert(obj); return obj; }
260 //! static_cast<> overload -- Useful for implicit casts
262 operator handle<U>()const
263 { return handle<U>(static_cast<U*>(obj)); }
265 operator handle<const value_type>()const
266 { return handle<const value_type>(static_cast<const_pointer>(obj)); }
268 //! <tt> static_cast\<\> </tt> wrapper
269 template <class U> static
270 handle<T> cast_static(const handle<U> &x)
271 { return handle<T>(static_cast<T*>(x.get())); }
273 //! <tt> dynamic_cast\<\> </tt> wrapper
274 template <class U> static
275 handle<T> cast_dynamic(const handle<U> &x)
276 { return handle<T>(dynamic_cast<T*>(x.get())); }
278 //! <tt> const_cast\<\> </tt> wrapper
279 template <class U> static
280 handle<T> cast_const(const handle<U> &x)
281 { return handle<T>(const_cast<T*>(x.get())); }
283 //! <tt> reinterpret_cast\<\> </tt> wrapper
284 template <class U> static
285 handle<T> cast_reinterpret(const handle<U> &x)
286 { return handle<T>(reinterpret_cast<T*>(x.get())); }
288 template<class U> static handle<T> cast_static(const loose_handle<U> &x);
289 template<class U> static handle<T> cast_dynamic(const loose_handle<U> &x);
290 template<class U> static handle<T> cast_const(const loose_handle<U> &x);
291 template<class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
293 template<class U> static handle<T> cast_static(const rhandle<U> &x);
294 template<class U> static handle<T> cast_dynamic(const rhandle<U> &x);
295 template<class U> static handle<T> cast_const(const rhandle<U> &x);
296 template<class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
298 template<class U> static handle<T> cast_static(U* x);
299 template<class U> static handle<T> cast_dynamic(U* x);
300 template<class U> static handle<T> cast_const(U* x);
301 template<class U> static handle<T> cast_reinterpret(U* x);
303 //! Returns pointer to the object that is being wrapped
304 pointer get()const { return obj; }
306 //! More explicit bool cast
308 { return obj!=NULL; }
313 }; // END of template class handle
315 // ========================================================================
316 /*! \class rshared_object _handle.h ETL/handle
317 ** \brief Replaceable Shared Object Base Class
321 class rshared_object : public shared_object
324 mutable int rrefcount;
331 rshared_object():rrefcount(0),front_(0),back_(0) { }
344 { return rrefcount; }
345 }; // END of class rshared_object
347 // ========================================================================
348 /*! \class rhandle _handle.h ETL/handle
349 ** \brief Replaceable Object Handle
350 ** \see rshared_object, handle, loose_handle
354 class rhandle : public handle<T>
356 friend class rshared_object;
359 typedef T value_type;
360 typedef T& reference;
361 typedef const T& const_reference;
363 typedef const T* const_pointer;
364 typedef int count_type;
365 typedef int size_type;
368 using handle<value_type>::count;
369 using handle<value_type>::unique;
370 using handle<value_type>::operator bool;
371 using handle<value_type>::get;
372 using handle<value_type>::operator *;
373 using handle<value_type>::operator ->;
376 operator const handle<value_type>&()const
381 using handle<value_type>::obj;
383 rhandle<value_type> *prev_;
384 rhandle<value_type> *next_;
388 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
393 // If this is the first reversable handle
396 obj->front_=obj->back_=this;
401 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
407 void del_from_rlist()
409 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
413 // If this is the last reversable handle
414 if(obj->front_==obj->back_)
416 obj->front_=obj->back_=0;
422 obj->front_=(void*)next_;
427 obj->back_=(void*)prev_;
434 //! Default constructor - empty handle
437 //! Constructor that constructs from a pointer to new object
438 rhandle(pointer x):handle<T>(x)
440 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
441 if(obj)add_to_rlist();
444 rhandle(const handle<value_type> &x):handle<T>(x)
446 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
447 if(obj)add_to_rlist();
450 //! Default copy constructor
451 rhandle(const rhandle<value_type> &x):handle<T>(x)
453 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
454 if(obj)add_to_rlist();
457 //! Handle is released on deletion
458 ~rhandle() { detach(); }
460 //! Template Assignment operator
461 /*! \note This class may not be necessary, and may be removed
462 ** at some point in the future.
465 template <class U> const handle<value_type> &
466 operator=(const handle<U> &x)
473 obj=static_cast<value_type*>(x.get());
483 //! Assignment operator
484 rhandle<value_type> &
485 operator=(const rhandle<value_type> &x)
487 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
503 operator=(const handle<value_type> &x)
505 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
521 operator=(value_type* x)
523 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
538 //! Handle release procedure
539 /*! unref()'s the object and sets the internal object pointer to \c NULL */
543 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
544 if(obj)del_from_rlist();
545 handle<value_type>::detach();
549 // This will be reintroduced with a new function
550 //void release() { detach(); }
552 void reset() { detach(); }
554 //! Creates a new instance of a T object and puts it in the handle.
555 /*! Uses the default constructor */
556 void spawn() { operator=(handle<value_type>(new T())); }
558 //! Returns number of reversable instances
562 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
563 return obj?obj->rcount():0;
566 //! Returns true if there is only one instance of the object
570 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
571 assert(obj); return obj->front_==obj->back_;
575 int replace(const handle<value_type> &x)
577 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
579 assert(x.get()!=obj);
584 rhandle<value_type> *iter;
585 rhandle<value_type> *next;
587 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
598 for(;iter;iter=next,next=iter?iter->next_:0,i++)
600 assert(iter->get()==obj_);
604 assert(obj==x.get());
609 //! Swaps the values of two handles without reference counts
610 /*! \warning not yet implemented. \writeme */
612 swap(handle<value_type> &x);
622 }; // END of template class rhandle
630 // ========================================================================
631 /*! \class loose_handle _handle.h ETL/handle
632 ** \brief Loose Object Handle
633 ** \see shared_object, handle
641 typedef T value_type;
642 typedef T& reference;
643 typedef const T& const_reference;
645 typedef const T* const_pointer;
646 typedef int count_type;
647 typedef int size_type;
650 value_type *obj; //!< Pointer to object
654 //! Default constructor - empty handle
655 loose_handle():obj(0) {}
657 //! Constructor that constructs from a pointer to new object
658 loose_handle(pointer x):obj(x) { }
660 //! Default copy constructor
661 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
663 loose_handle(const handle<value_type> &x):obj(x.get()) { }
665 template <class U> const loose_handle<value_type> &
666 operator=(const handle<U> &x)
671 obj=static_cast<value_type*>(x.get());
675 template <class U> const loose_handle<value_type> &
676 operator=(const loose_handle<U> &x)
681 obj=static_cast<value_type*>(x.get());
685 //! Assignment operator
686 const loose_handle<value_type> &
687 operator=(const loose_handle<value_type> &x)
696 //! Swaps the values of two handles without reference counts
697 loose_handle<value_type> &
698 swap(loose_handle<value_type> &x)
706 //! Handle release procedure
707 void detach() { obj=0; }
709 // This will be reintroduced with a new function
710 //void release() { detach(); }
712 void reset() { detach(); }
714 bool empty()const { return obj==0; }
716 handle<value_type> clone()const { assert(obj); return obj->clone(); }
718 //! Returns a constant handle to our object
719 loose_handle<const value_type> constant()const { return *this; }
721 //! Returns number of instances
724 { return obj?obj->count():0; }
728 { assert(obj); return *obj; }
732 { assert(obj); return obj; }
734 //! static_cast<> overload
736 //operator loose_handle<U>()const
737 //{ return loose_handle<U>(static_cast<U*>(obj)); }
739 //! static_cast<> overload (for consts)
740 operator loose_handle<const value_type>()const
741 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
743 operator handle<value_type>()const
744 { return handle<value_type>(obj); }
746 operator rhandle<value_type>()const
747 { return rhandle<value_type>(obj); }
749 //! Returns pointer to the object that is being wrapped
750 pointer get()const { return obj; }
752 //! More explicit bool cast
760 void ref() { if(obj)obj->ref(); }
762 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
763 }; // END of template class loose_handle
768 template<class T> template<class U> handle<T>
769 handle<T>::cast_static(const loose_handle<U> &x)
770 { return handle<T>(static_cast<T*>(x.get())); }
772 template <class T> template <class U> handle<T>
773 handle<T>::cast_dynamic(const loose_handle<U> &x)
774 { return handle<T>(dynamic_cast<T*>(x.get())); }
776 template <class T> template <class U> handle<T>
777 handle<T>::cast_const(const loose_handle<U> &x)
778 { return handle<T>(const_cast<T*>(x.get())); }
780 template <class T> template <class U> handle<T>
781 handle<T>::cast_reinterpret(const loose_handle<U> &x)
782 { return handle<T>(reinterpret_cast<T*>(x.get())); }
786 template <class T> template <class U> handle<T>
787 handle<T>::cast_static(const rhandle<U> &x)
788 { return handle<T>(static_cast<T*>(x.get())); }
790 template <class T> template <class U> handle<T>
791 handle<T>::cast_dynamic(const rhandle<U> &x)
792 { return handle<T>(dynamic_cast<T*>(x.get())); }
794 template <class T> template <class U> handle<T>
795 handle<T>::cast_const(const rhandle<U> &x)
796 { return handle<T>(const_cast<T*>(x.get())); }
798 template <class T> template <class U> handle<T>
799 handle<T>::cast_reinterpret(const rhandle<U> &x)
800 { return handle<T>(reinterpret_cast<T*>(x.get())); }
804 template <class T> template <class U> handle<T>
805 handle<T>::cast_static(U* x)
806 { return handle<T>(static_cast<T*>(x)); }
808 template <class T> template <class U> handle<T>
809 handle<T>::cast_dynamic(U* x)
810 { return handle<T>(dynamic_cast<T*>(x)); }
812 template <class T> template <class U> handle<T>
813 handle<T>::cast_const(U* x)
814 { return handle<T>(const_cast<T*>(x)); }
816 template <class T> template <class U> handle<T>
817 handle<T>::cast_reinterpret(U* x)
818 { return handle<T>(reinterpret_cast<T*>(x)); }
824 template <class T,class U> bool
825 operator==(const handle<T> &lhs,const handle<U> &rhs)
826 { return (lhs.get()==rhs.get()); }
827 template <class T,class U> bool
828 operator==(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
829 { return (lhs.get()==rhs.get()); }
830 template <class T,class U> bool
831 operator==(const handle<T> &lhs,const loose_handle<U> &rhs)
832 { return (lhs.get()==rhs.get()); }
833 template <class T,class U> bool
834 operator==(const loose_handle<T> &lhs,const handle<U> &rhs)
835 { return (lhs.get()==rhs.get()); }
836 template <class T> bool
837 operator==(const handle<T> &lhs,const T *rhs)
838 { return (lhs.get()==rhs); }
839 template <class T> bool
840 operator==(const loose_handle<T> &lhs,const T *rhs)
841 { return (lhs.get()==rhs); }
842 template <class T> bool
843 operator==(const T *lhs,const handle<T> &rhs)
844 { return (lhs==rhs.get()); }
845 template <class T> bool
846 operator==(const T *lhs,const loose_handle<T> &rhs)
847 { return (lhs==rhs.get()); }
850 template <class T,class U> bool
851 operator!=(const handle<T> &lhs,const handle<U> &rhs)
852 { return (lhs.get()!=rhs.get()); }
853 template <class T,class U> bool
854 operator!=(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
855 { return (lhs.get()!=rhs.get()); }
856 template <class T,class U> bool
857 operator!=(const handle<T> &lhs,const loose_handle<U> &rhs)
858 { return (lhs.get()!=rhs.get()); }
859 template <class T,class U> bool
860 operator!=(const loose_handle<T> &lhs,const handle<U> &rhs)
861 { return (lhs.get()!=rhs.get()); }
862 template <class T> bool
863 operator!=(const handle<T> &lhs,const T *rhs)
864 { return (lhs.get()!=rhs); }
865 template <class T> bool
866 operator!=(const loose_handle<T> &lhs,const T *rhs)
867 { return (lhs.get()!=rhs); }
868 template <class T> bool
869 operator!=(const T *lhs,const handle<T> &rhs)
870 { return (lhs!=rhs.get()); }
871 template <class T> bool
872 operator!=(const T *lhs,const loose_handle<T> &rhs)
873 { return (lhs!=rhs.get()); }
876 template <class T,class U> bool
877 operator<(const handle<T> &lhs,const handle<U> &rhs)
878 { return (lhs.get()<rhs.get()); }
879 template <class T,class U> bool
880 operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
881 { return (lhs.get()<rhs.get()); }
882 template <class T,class U> bool
883 operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
884 { return (lhs.get()<rhs.get()); }
885 template <class T,class U> bool
886 operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
887 { return (lhs.get()<rhs.get()); }
888 template <class T> bool
889 operator<(const handle<T> &lhs,const T *rhs)
890 { return (lhs.get()<rhs); }
891 template <class T> bool
892 operator<(const loose_handle<T> &lhs,const T *rhs)
893 { return (lhs.get()<rhs); }
894 template <class T> bool
895 operator<(const T *lhs,const handle<T> &rhs)
896 { return (lhs<rhs.get()); }
897 template <class T> bool
898 operator<(const T *lhs,const loose_handle<T> &rhs)
899 { return (lhs<rhs.get()); }
903 /* === E N D =============================================================== */