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 ======================================================= */
34 // include the next line in an attempt to increase stability
35 #define ETL_LOCK_REFCOUNTS
38 #ifdef ETL_LOCK_REFCOUNTS
39 #include <glibmm/thread.h>
42 /* === M A C R O S ========================================================= */
44 /* === T Y P E D E F S ===================================================== */
46 #define ETL_SELF_DELETING_SHARED_OBJECT
48 /* === C L A S S E S & S T R U C T S ======================================= */
51 #define assert_cast static_cast
53 #define assert_cast dynamic_cast
59 // Forward Declarations
60 template <class T> class handle;
61 template <class T> class loose_handle;
62 template <class T> class rhandle;
65 // ========================================================================
66 /*! \class shared_object _handle.h ETL/handle
67 ** \brief Shared Object Base Class
68 ** \see handle, loose_handle
75 #ifdef ETL_LOCK_REFCOUNTS
76 mutable Glib::Mutex mutex;
80 shared_object():refcount(0) { }
82 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
83 virtual ~shared_object() { }
91 #ifdef ETL_LOCK_REFCOUNTS
92 Glib::Mutex::Lock lock(mutex);
94 assert(refcount>=0); refcount++;
97 //! Returns \c false if object needs to be deleted
100 #ifdef ETL_LOCK_REFCOUNTS
101 Glib::Mutex::Lock lock(mutex);
108 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
110 #ifdef ETL_LOCK_REFCOUNTS
123 #ifdef ETL_LOCK_REFCOUNTS
124 Glib::Mutex::Lock lock(mutex);
128 }; // END of class shared_object
130 // ========================================================================
131 /*! \class virtual_shared_object _handle.h ETL/handle
132 ** \brief Virtual Shared Object Base Class
133 ** \see handle, loose_handle
136 class virtual_shared_object
139 virtual_shared_object() { }
141 virtual ~virtual_shared_object()=0;
142 virtual void ref()const=0;
143 virtual bool unref()const=0;
144 virtual int count()const=0;
145 virtual virtual_shared_object *clone()=0;
146 }; // END of class virtual_shared_object
148 // ========================================================================
149 /*! \class handle _handle.h ETL/handle
150 ** \brief Object Handle
151 ** \see shared_object, loose_handle
159 typedef T value_type;
160 typedef T& reference;
161 typedef const T& const_reference;
163 typedef const T* const_pointer;
164 typedef int count_type;
165 typedef int size_type;
168 value_type *obj; //!< Pointer to object
172 //! Default constructor - empty handle
173 handle():obj(NULL) {}
175 //! Constructor that constructs from a pointer to new object
176 handle(pointer x):obj(x)
182 //! Default copy constructor
183 handle(const handle<value_type> &x):obj(x.get())
189 //! Handle is released on deletion
190 ~handle() { detach(); }
192 //! Template Assignment operator
193 /*! \note This class may not be necessary, and may be removed
194 ** at some point in the future.
197 template <class U> handle<value_type> &
198 operator=(const handle<U> &x)
205 obj=static_cast<value_type*>(x.get());
211 //! Assignment operator
213 operator=(const handle<value_type> &x)
225 //! Swaps the values of two handles without reference counts
227 swap(handle<value_type> &x)
235 //! Handle detach procedure
236 /*! unref()'s the object and sets the internal object pointer to \c NULL */
242 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
246 if(xobj && !xobj->unref())
251 // This will be reintroduced with a new function
252 //void release() { detach(); }
254 void reset() { detach(); }
256 bool empty()const { return obj==0; }
258 //! Creates a new instance of a T object and puts it in the handle.
259 /*! Uses the default constructor */
260 void spawn() { operator=(handle(new T())); }
262 handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
264 //! Returns a constant handle to our object
265 handle<const value_type> constant()const { assert(obj); return *this; }
267 //! Returns number of instances
270 { return obj?obj->count():0; }
272 //! Returns true if there is only one instance of the object
275 { assert(obj); return count()==1; }
279 { assert(obj); return *obj; }
283 { assert(obj); return obj; }
285 //! More explicit bool cast
287 { return obj!=NULL; }
289 operator handle<const value_type>()const
290 { return handle<const value_type>(static_cast<const_pointer>(obj)); }
293 //! <tt> static_cast\<\> </tt> wrapper
294 template <class U> static
295 handle<T> cast_static(const handle<U> &x)
296 { return handle<T>(static_cast<T*>(x.get())); }
298 //! <tt> dynamic_cast\<\> </tt> wrapper
299 template <class U> static
300 handle<T> cast_dynamic(const handle<U> &x)
301 { return handle<T>(dynamic_cast<T*>(x.get())); }
303 //! <tt> const_cast\<\> </tt> wrapper
304 template <class U> static
305 handle<T> cast_const(const handle<U> &x)
306 { return handle<T>(const_cast<T*>(x.get())); }
308 //! <tt> reinterpret_cast\<\> </tt> wrapper
309 template <class U> static
310 handle<T> cast_reinterpret(const handle<U> &x)
311 { return handle<T>(reinterpret_cast<T*>(x.get())); }
313 template<class U> static handle<T> cast_static(const loose_handle<U> &x);
314 template<class U> static handle<T> cast_dynamic(const loose_handle<U> &x);
315 template<class U> static handle<T> cast_const(const loose_handle<U> &x);
316 template<class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
318 template<class U> static handle<T> cast_static(const rhandle<U> &x);
319 template<class U> static handle<T> cast_dynamic(const rhandle<U> &x);
320 template<class U> static handle<T> cast_const(const rhandle<U> &x);
321 template<class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
323 template<class U> static handle<T> cast_static(U* x);
324 template<class U> static handle<T> cast_dynamic(U* x);
325 template<class U> static handle<T> cast_const(U* x);
326 template<class U> static handle<T> cast_reinterpret(U* x);
328 //! Returns pointer to the object that is being wrapped
329 pointer get()const { return obj; }
335 //! static_cast<> overload -- Useful for implicit casts
337 operator handle<U>()const
338 { return handle<U>(static_cast<U*>(obj)); }
339 }; // END of template class handle
341 // ========================================================================
342 /*! \class rshared_object _handle.h ETL/handle
343 ** \brief Replaceable Shared Object Base Class
347 class rshared_object : public shared_object
350 mutable int rrefcount;
357 rshared_object():rrefcount(0),front_(0),back_(0) { }
370 { return rrefcount; }
371 }; // END of class rshared_object
373 // ========================================================================
374 /*! \class rhandle _handle.h ETL/handle
375 ** \brief Replaceable Object Handle
376 ** \see rshared_object, handle, loose_handle
380 class rhandle : public handle<T>
382 friend class rshared_object;
385 typedef T value_type;
386 typedef T& reference;
387 typedef const T& const_reference;
389 typedef const T* const_pointer;
390 typedef int count_type;
391 typedef int size_type;
394 using handle<value_type>::count;
395 using handle<value_type>::unique;
396 using handle<value_type>::operator bool;
397 using handle<value_type>::get;
398 using handle<value_type>::operator *;
399 using handle<value_type>::operator ->;
402 operator const handle<value_type>&()const
407 using handle<value_type>::obj;
409 rhandle<value_type> *prev_;
410 rhandle<value_type> *next_;
414 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
419 // If this is the first reversible handle
422 obj->front_=obj->back_=this;
427 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
433 void del_from_rlist()
435 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
439 // If this is the last reversible handle
440 if(obj->front_==obj->back_)
442 obj->front_=obj->back_=0;
448 obj->front_=(void*)next_;
453 obj->back_=(void*)prev_;
460 //! Default constructor - empty handle
463 //! Constructor that constructs from a pointer to new object
464 rhandle(pointer x):handle<T>(x)
466 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
467 if(obj)add_to_rlist();
470 rhandle(const handle<value_type> &x):handle<T>(x)
472 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
473 if(obj)add_to_rlist();
476 //! Default copy constructor
477 rhandle(const rhandle<value_type> &x):handle<T>(x)
479 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
480 if(obj)add_to_rlist();
483 //! Handle is released on deletion
484 ~rhandle() { detach(); }
486 //! Template Assignment operator
487 /*! \note This class may not be necessary, and may be removed
488 ** at some point in the future.
491 template <class U> const handle<value_type> &
492 operator=(const handle<U> &x)
499 obj=static_cast<value_type*>(x.get());
509 //! Assignment operator
510 rhandle<value_type> &
511 operator=(const rhandle<value_type> &x)
513 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
529 operator=(const handle<value_type> &x)
531 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
547 operator=(value_type* x)
549 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
564 //! Handle release procedure
565 /*! unref()'s the object and sets the internal object pointer to \c NULL */
569 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
570 if(obj)del_from_rlist();
571 handle<value_type>::detach();
575 // This will be reintroduced with a new function
576 //void release() { detach(); }
578 void reset() { detach(); }
580 //! Creates a new instance of a T object and puts it in the handle.
581 /*! Uses the default constructor */
582 void spawn() { operator=(handle<value_type>(new T())); }
584 //! Returns number of reversible instances
588 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
589 return obj?obj->rcount():0;
592 //! Returns true if there is only one instance of the object
596 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
597 assert(obj); return obj->front_==obj->back_;
601 int replace(const handle<value_type> &x)
603 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
605 assert(x.get()!=obj);
610 rhandle<value_type> *iter;
611 rhandle<value_type> *next;
613 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
624 for(;iter;iter=next,next=iter?iter->next_:0,i++)
626 assert(iter->get()==obj_);
630 assert(obj==x.get());
635 //! Swaps the values of two handles without reference counts
636 /*! \warning not yet implemented. \writeme */
638 swap(handle<value_type> &x);
648 }; // END of template class rhandle
656 // ========================================================================
657 /*! \class loose_handle _handle.h ETL/handle
658 ** \brief Loose Object Handle
659 ** \see shared_object, handle
667 typedef T value_type;
668 typedef T& reference;
669 typedef const T& const_reference;
671 typedef const T* const_pointer;
672 typedef int count_type;
673 typedef int size_type;
676 value_type *obj; //!< Pointer to object
680 //! Default constructor - empty handle
681 loose_handle():obj(0) {}
683 //! Constructor that constructs from a pointer to new object
684 loose_handle(pointer x):obj(x) { }
686 //! Default copy constructor
687 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
689 loose_handle(const handle<value_type> &x):obj(x.get()) { }
691 template <class U> const loose_handle<value_type> &
692 operator=(const handle<U> &x)
697 obj=static_cast<value_type*>(x.get());
701 template <class U> const loose_handle<value_type> &
702 operator=(const loose_handle<U> &x)
707 obj=static_cast<value_type*>(x.get());
711 //! Assignment operator
712 const loose_handle<value_type> &
713 operator=(const loose_handle<value_type> &x)
722 //! Swaps the values of two handles without reference counts
723 loose_handle<value_type> &
724 swap(loose_handle<value_type> &x)
732 //! Handle release procedure
733 void detach() { obj=0; }
735 // This will be reintroduced with a new function
736 //void release() { detach(); }
738 void reset() { detach(); }
740 bool empty()const { return obj==0; }
742 handle<value_type> clone()const { assert(obj); return obj->clone(); }
744 //! Returns a constant handle to our object
745 loose_handle<const value_type> constant()const { return *this; }
747 //! Returns number of instances
750 { return obj?obj->count():0; }
754 { assert(obj); return *obj; }
758 { assert(obj); return obj; }
760 //! static_cast<> overload
762 //operator loose_handle<U>()const
763 //{ return loose_handle<U>(static_cast<U*>(obj)); }
765 //! static_cast<> overload (for consts)
766 operator loose_handle<const value_type>()const
767 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
769 operator handle<value_type>()const
770 { return handle<value_type>(obj); }
772 operator rhandle<value_type>()const
773 { return rhandle<value_type>(obj); }
775 //! Returns pointer to the object that is being wrapped
776 pointer get()const { return obj; }
778 //! More explicit bool cast
786 void ref() { if(obj)obj->ref(); }
788 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
789 }; // END of template class loose_handle
794 template<class T> template<class U> handle<T>
795 handle<T>::cast_static(const loose_handle<U> &x)
796 { return handle<T>(static_cast<T*>(x.get())); }
798 template <class T> template <class U> handle<T>
799 handle<T>::cast_dynamic(const loose_handle<U> &x)
800 { return handle<T>(dynamic_cast<T*>(x.get())); }
802 template <class T> template <class U> handle<T>
803 handle<T>::cast_const(const loose_handle<U> &x)
804 { return handle<T>(const_cast<T*>(x.get())); }
806 template <class T> template <class U> handle<T>
807 handle<T>::cast_reinterpret(const loose_handle<U> &x)
808 { return handle<T>(reinterpret_cast<T*>(x.get())); }
812 template <class T> template <class U> handle<T>
813 handle<T>::cast_static(const rhandle<U> &x)
814 { return handle<T>(static_cast<T*>(x.get())); }
816 template <class T> template <class U> handle<T>
817 handle<T>::cast_dynamic(const rhandle<U> &x)
818 { return handle<T>(dynamic_cast<T*>(x.get())); }
820 template <class T> template <class U> handle<T>
821 handle<T>::cast_const(const rhandle<U> &x)
822 { return handle<T>(const_cast<T*>(x.get())); }
824 template <class T> template <class U> handle<T>
825 handle<T>::cast_reinterpret(const rhandle<U> &x)
826 { return handle<T>(reinterpret_cast<T*>(x.get())); }
830 template <class T> template <class U> handle<T>
831 handle<T>::cast_static(U* x)
832 { return handle<T>(static_cast<T*>(x)); }
834 template <class T> template <class U> handle<T>
835 handle<T>::cast_dynamic(U* x)
836 { return handle<T>(dynamic_cast<T*>(x)); }
838 template <class T> template <class U> handle<T>
839 handle<T>::cast_const(U* x)
840 { return handle<T>(const_cast<T*>(x)); }
842 template <class T> template <class U> handle<T>
843 handle<T>::cast_reinterpret(U* x)
844 { return handle<T>(reinterpret_cast<T*>(x)); }
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()); }
902 template <class T,class U> bool
903 operator<(const handle<T> &lhs,const handle<U> &rhs)
904 { return (lhs.get()<rhs.get()); }
905 template <class T,class U> bool
906 operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
907 { return (lhs.get()<rhs.get()); }
908 template <class T,class U> bool
909 operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
910 { return (lhs.get()<rhs.get()); }
911 template <class T,class U> bool
912 operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
913 { return (lhs.get()<rhs.get()); }
914 template <class T> bool
915 operator<(const handle<T> &lhs,const T *rhs)
916 { return (lhs.get()<rhs); }
917 template <class T> bool
918 operator<(const loose_handle<T> &lhs,const T *rhs)
919 { return (lhs.get()<rhs); }
920 template <class T> bool
921 operator<(const T *lhs,const handle<T> &rhs)
922 { return (lhs<rhs.get()); }
923 template <class T> bool
924 operator<(const T *lhs,const loose_handle<T> &rhs)
925 { return (lhs<rhs.get()); }
929 /* === E N D =============================================================== */