1 /* === E T L =============================================================== */
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 //! More explicit bool cast
262 { return obj!=NULL; }
264 operator handle<const value_type>()const
265 { 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; }
310 //! static_cast<> overload -- Useful for implicit casts
312 operator handle<U>()const
313 { return handle<U>(static_cast<U*>(obj)); }
314 }; // END of template class handle
316 // ========================================================================
317 /*! \class rshared_object _handle.h ETL/handle
318 ** \brief Replaceable Shared Object Base Class
322 class rshared_object : public shared_object
325 mutable int rrefcount;
332 rshared_object():rrefcount(0),front_(0),back_(0) { }
345 { return rrefcount; }
346 }; // END of class rshared_object
348 // ========================================================================
349 /*! \class rhandle _handle.h ETL/handle
350 ** \brief Replaceable Object Handle
351 ** \see rshared_object, handle, loose_handle
355 class rhandle : public handle<T>
357 friend class rshared_object;
360 typedef T value_type;
361 typedef T& reference;
362 typedef const T& const_reference;
364 typedef const T* const_pointer;
365 typedef int count_type;
366 typedef int size_type;
369 using handle<value_type>::count;
370 using handle<value_type>::unique;
371 using handle<value_type>::operator bool;
372 using handle<value_type>::get;
373 using handle<value_type>::operator *;
374 using handle<value_type>::operator ->;
377 operator const handle<value_type>&()const
382 using handle<value_type>::obj;
384 rhandle<value_type> *prev_;
385 rhandle<value_type> *next_;
389 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
394 // If this is the first reversible handle
397 obj->front_=obj->back_=this;
402 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
408 void del_from_rlist()
410 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
414 // If this is the last reversible handle
415 if(obj->front_==obj->back_)
417 obj->front_=obj->back_=0;
423 obj->front_=(void*)next_;
428 obj->back_=(void*)prev_;
435 //! Default constructor - empty handle
438 //! Constructor that constructs from a pointer to new object
439 rhandle(pointer x):handle<T>(x)
441 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
442 if(obj)add_to_rlist();
445 rhandle(const handle<value_type> &x):handle<T>(x)
447 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
448 if(obj)add_to_rlist();
451 //! Default copy constructor
452 rhandle(const rhandle<value_type> &x):handle<T>(x)
454 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
455 if(obj)add_to_rlist();
458 //! Handle is released on deletion
459 ~rhandle() { detach(); }
461 //! Template Assignment operator
462 /*! \note This class may not be necessary, and may be removed
463 ** at some point in the future.
466 template <class U> const handle<value_type> &
467 operator=(const handle<U> &x)
474 obj=static_cast<value_type*>(x.get());
484 //! Assignment operator
485 rhandle<value_type> &
486 operator=(const rhandle<value_type> &x)
488 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
504 operator=(const handle<value_type> &x)
506 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
522 operator=(value_type* x)
524 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
539 //! Handle release procedure
540 /*! unref()'s the object and sets the internal object pointer to \c NULL */
544 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
545 if(obj)del_from_rlist();
546 handle<value_type>::detach();
550 // This will be reintroduced with a new function
551 //void release() { detach(); }
553 void reset() { detach(); }
555 //! Creates a new instance of a T object and puts it in the handle.
556 /*! Uses the default constructor */
557 void spawn() { operator=(handle<value_type>(new T())); }
559 //! Returns number of reversible instances
563 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
564 return obj?obj->rcount():0;
567 //! Returns true if there is only one instance of the object
571 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
572 assert(obj); return obj->front_==obj->back_;
576 int replace(const handle<value_type> &x)
578 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
580 assert(x.get()!=obj);
585 rhandle<value_type> *iter;
586 rhandle<value_type> *next;
588 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
599 for(;iter;iter=next,next=iter?iter->next_:0,i++)
601 assert(iter->get()==obj_);
605 assert(obj==x.get());
610 //! Swaps the values of two handles without reference counts
611 /*! \warning not yet implemented. \writeme */
613 swap(handle<value_type> &x);
623 }; // END of template class rhandle
631 // ========================================================================
632 /*! \class loose_handle _handle.h ETL/handle
633 ** \brief Loose Object Handle
634 ** \see shared_object, handle
642 typedef T value_type;
643 typedef T& reference;
644 typedef const T& const_reference;
646 typedef const T* const_pointer;
647 typedef int count_type;
648 typedef int size_type;
651 value_type *obj; //!< Pointer to object
655 //! Default constructor - empty handle
656 loose_handle():obj(0) {}
658 //! Constructor that constructs from a pointer to new object
659 loose_handle(pointer x):obj(x) { }
661 //! Default copy constructor
662 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
664 loose_handle(const handle<value_type> &x):obj(x.get()) { }
666 template <class U> const loose_handle<value_type> &
667 operator=(const handle<U> &x)
672 obj=static_cast<value_type*>(x.get());
676 template <class U> const loose_handle<value_type> &
677 operator=(const loose_handle<U> &x)
682 obj=static_cast<value_type*>(x.get());
686 //! Assignment operator
687 const loose_handle<value_type> &
688 operator=(const loose_handle<value_type> &x)
697 //! Swaps the values of two handles without reference counts
698 loose_handle<value_type> &
699 swap(loose_handle<value_type> &x)
707 //! Handle release procedure
708 void detach() { obj=0; }
710 // This will be reintroduced with a new function
711 //void release() { detach(); }
713 void reset() { detach(); }
715 bool empty()const { return obj==0; }
717 handle<value_type> clone()const { assert(obj); return obj->clone(); }
719 //! Returns a constant handle to our object
720 loose_handle<const value_type> constant()const { return *this; }
722 //! Returns number of instances
725 { return obj?obj->count():0; }
729 { assert(obj); return *obj; }
733 { assert(obj); return obj; }
735 //! static_cast<> overload
737 //operator loose_handle<U>()const
738 //{ return loose_handle<U>(static_cast<U*>(obj)); }
740 //! static_cast<> overload (for consts)
741 operator loose_handle<const value_type>()const
742 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
744 operator handle<value_type>()const
745 { return handle<value_type>(obj); }
747 operator rhandle<value_type>()const
748 { return rhandle<value_type>(obj); }
750 //! Returns pointer to the object that is being wrapped
751 pointer get()const { return obj; }
753 //! More explicit bool cast
761 void ref() { if(obj)obj->ref(); }
763 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
764 }; // END of template class loose_handle
769 template<class T> template<class U> handle<T>
770 handle<T>::cast_static(const loose_handle<U> &x)
771 { return handle<T>(static_cast<T*>(x.get())); }
773 template <class T> template <class U> handle<T>
774 handle<T>::cast_dynamic(const loose_handle<U> &x)
775 { return handle<T>(dynamic_cast<T*>(x.get())); }
777 template <class T> template <class U> handle<T>
778 handle<T>::cast_const(const loose_handle<U> &x)
779 { return handle<T>(const_cast<T*>(x.get())); }
781 template <class T> template <class U> handle<T>
782 handle<T>::cast_reinterpret(const loose_handle<U> &x)
783 { return handle<T>(reinterpret_cast<T*>(x.get())); }
787 template <class T> template <class U> handle<T>
788 handle<T>::cast_static(const rhandle<U> &x)
789 { return handle<T>(static_cast<T*>(x.get())); }
791 template <class T> template <class U> handle<T>
792 handle<T>::cast_dynamic(const rhandle<U> &x)
793 { return handle<T>(dynamic_cast<T*>(x.get())); }
795 template <class T> template <class U> handle<T>
796 handle<T>::cast_const(const rhandle<U> &x)
797 { return handle<T>(const_cast<T*>(x.get())); }
799 template <class T> template <class U> handle<T>
800 handle<T>::cast_reinterpret(const rhandle<U> &x)
801 { return handle<T>(reinterpret_cast<T*>(x.get())); }
805 template <class T> template <class U> handle<T>
806 handle<T>::cast_static(U* x)
807 { return handle<T>(static_cast<T*>(x)); }
809 template <class T> template <class U> handle<T>
810 handle<T>::cast_dynamic(U* x)
811 { return handle<T>(dynamic_cast<T*>(x)); }
813 template <class T> template <class U> handle<T>
814 handle<T>::cast_const(U* x)
815 { return handle<T>(const_cast<T*>(x)); }
817 template <class T> template <class U> handle<T>
818 handle<T>::cast_reinterpret(U* x)
819 { return handle<T>(reinterpret_cast<T*>(x)); }
825 template <class T,class U> bool
826 operator==(const handle<T> &lhs,const handle<U> &rhs)
827 { return (lhs.get()==rhs.get()); }
828 template <class T,class U> bool
829 operator==(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
830 { return (lhs.get()==rhs.get()); }
831 template <class T,class U> bool
832 operator==(const handle<T> &lhs,const loose_handle<U> &rhs)
833 { return (lhs.get()==rhs.get()); }
834 template <class T,class U> bool
835 operator==(const loose_handle<T> &lhs,const handle<U> &rhs)
836 { return (lhs.get()==rhs.get()); }
837 template <class T> bool
838 operator==(const handle<T> &lhs,const T *rhs)
839 { return (lhs.get()==rhs); }
840 template <class T> bool
841 operator==(const loose_handle<T> &lhs,const T *rhs)
842 { return (lhs.get()==rhs); }
843 template <class T> bool
844 operator==(const T *lhs,const handle<T> &rhs)
845 { return (lhs==rhs.get()); }
846 template <class T> bool
847 operator==(const T *lhs,const loose_handle<T> &rhs)
848 { return (lhs==rhs.get()); }
851 template <class T,class U> bool
852 operator!=(const handle<T> &lhs,const handle<U> &rhs)
853 { return (lhs.get()!=rhs.get()); }
854 template <class T,class U> bool
855 operator!=(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
856 { return (lhs.get()!=rhs.get()); }
857 template <class T,class U> bool
858 operator!=(const handle<T> &lhs,const loose_handle<U> &rhs)
859 { return (lhs.get()!=rhs.get()); }
860 template <class T,class U> bool
861 operator!=(const loose_handle<T> &lhs,const handle<U> &rhs)
862 { return (lhs.get()!=rhs.get()); }
863 template <class T> bool
864 operator!=(const handle<T> &lhs,const T *rhs)
865 { return (lhs.get()!=rhs); }
866 template <class T> bool
867 operator!=(const loose_handle<T> &lhs,const T *rhs)
868 { return (lhs.get()!=rhs); }
869 template <class T> bool
870 operator!=(const T *lhs,const handle<T> &rhs)
871 { return (lhs!=rhs.get()); }
872 template <class T> bool
873 operator!=(const T *lhs,const loose_handle<T> &rhs)
874 { return (lhs!=rhs.get()); }
877 template <class T,class U> bool
878 operator<(const handle<T> &lhs,const handle<U> &rhs)
879 { return (lhs.get()<rhs.get()); }
880 template <class T,class U> bool
881 operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
882 { return (lhs.get()<rhs.get()); }
883 template <class T,class U> bool
884 operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
885 { return (lhs.get()<rhs.get()); }
886 template <class T,class U> bool
887 operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
888 { return (lhs.get()<rhs.get()); }
889 template <class T> bool
890 operator<(const handle<T> &lhs,const T *rhs)
891 { return (lhs.get()<rhs); }
892 template <class T> bool
893 operator<(const loose_handle<T> &lhs,const T *rhs)
894 { return (lhs.get()<rhs); }
895 template <class T> bool
896 operator<(const T *lhs,const handle<T> &rhs)
897 { return (lhs<rhs.get()); }
898 template <class T> bool
899 operator<(const T *lhs,const loose_handle<T> &rhs)
900 { return (lhs<rhs.get()); }
904 /* === E N D =============================================================== */