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;
146 value_type *obj; //!< Pointer to object
150 //! Default constructor - empty handle
151 handle():obj(NULL) {}
153 //! Constructor that constructs from a pointer to new object
154 handle(pointer x):obj(x)
160 //! Default copy constructor
161 handle(const handle<value_type> &x):obj(x.get())
167 //! Handle is released on deletion
168 ~handle() { detach(); }
170 //! Template Assignment operator
171 /*! \note This class may not be necessary, and may be removed
172 ** at some point in the future.
175 template <class U> handle<value_type> &
176 operator=(const handle<U> &x)
183 obj=static_cast<value_type*>(x.get());
189 //! Assignment operator
191 operator=(const handle<value_type> &x)
203 //! Swaps the values of two handles without reference counts
205 swap(handle<value_type> &x)
213 //! Handle detach procedure
214 /*! unref()'s the object and sets the internal object pointer to \c NULL */
220 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
224 if(xobj && !xobj->unref())
229 // This will be reintroduced with a new function
230 //void release() { detach(); }
232 void reset() { detach(); }
234 bool empty()const { return obj==0; }
236 //! Creates a new instance of a T object and puts it in the handle.
237 /*! Uses the default constructor */
238 void spawn() { operator=(handle(new T())); }
240 handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
242 //! Returns a constant handle to our object
243 handle<const value_type> constant()const { assert(obj); return *this; }
245 //! Returns number of instances
248 { return obj?obj->count():0; }
250 //! Returns true if there is only one instance of the object
253 { assert(obj); return count()==1; }
257 { assert(obj); return *obj; }
261 { assert(obj); return obj; }
263 //! More explicit bool cast
265 { return obj!=NULL; }
267 operator handle<const value_type>()const
268 { return handle<const value_type>(static_cast<const_pointer>(obj)); }
270 //! <tt> static_cast\<\> </tt> wrapper
271 template <class U> static handle<T> cast_static (const handle<U> &x) { return handle<T>(static_cast <T*>(x.get())); }
272 //! <tt> dynamic_cast\<\> </tt> wrapper
273 template <class U> static handle<T> cast_dynamic (const handle<U> &x) { return handle<T>(dynamic_cast <T*>(x.get())); }
274 //! <tt> const_cast\<\> </tt> wrapper
275 template <class U> static handle<T> cast_const (const handle<U> &x) { return handle<T>(const_cast <T*>(x.get())); }
276 //! <tt> reinterpret_cast\<\> </tt> wrapper
277 template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
279 template <class U> static handle<T> cast_static (const loose_handle<U> &x);
280 template <class U> static handle<T> cast_dynamic (const loose_handle<U> &x);
281 template <class U> static handle<T> cast_const (const loose_handle<U> &x);
282 template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
284 template <class U> static handle<T> cast_static (const rhandle<U> &x);
285 template <class U> static handle<T> cast_dynamic (const rhandle<U> &x);
286 template <class U> static handle<T> cast_const (const rhandle<U> &x);
287 template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
289 template <class U> static handle<T> cast_static (U* x);
290 template <class U> static handle<T> cast_dynamic (U* x);
291 template <class U> static handle<T> cast_const (U* x);
292 template <class U> static handle<T> cast_reinterpret(U* x);
294 //! Returns pointer to the object that is being wrapped
295 pointer get()const { return obj; }
301 //! static_cast<> overload -- Useful for implicit casts
303 operator handle<U>()const
304 { return handle<U>(static_cast<U*>(obj)); }
305 }; // END of template class handle
307 // ========================================================================
308 /*! \class rshared_object _handle.h ETL/handle
309 ** \brief Replaceable Shared Object Base Class
313 class rshared_object : public shared_object
316 mutable int rrefcount;
323 rshared_object():rrefcount(0),front_(0),back_(0) { }
336 { return rrefcount; }
337 }; // END of class rshared_object
339 // ========================================================================
340 /*! \class rhandle _handle.h ETL/handle
341 ** \brief Replaceable Object Handle
342 ** \see rshared_object, handle, loose_handle
346 class rhandle : public handle<T>
348 friend class rshared_object;
351 typedef T value_type;
352 typedef T& reference;
353 typedef const T& const_reference;
355 typedef const T* const_pointer;
356 typedef int count_type;
357 typedef int size_type;
360 using handle<value_type>::count;
361 using handle<value_type>::unique;
362 using handle<value_type>::operator bool;
363 using handle<value_type>::get;
364 using handle<value_type>::operator *;
365 using handle<value_type>::operator ->;
368 operator const handle<value_type>&()const
373 using handle<value_type>::obj;
375 rhandle<value_type> *prev_;
376 rhandle<value_type> *next_;
380 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
385 // If this is the first reversible handle
388 obj->front_=obj->back_=this;
393 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
399 void del_from_rlist()
401 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
405 // If this is the last reversible handle
406 if(obj->front_==obj->back_)
408 obj->front_=obj->back_=0;
414 obj->front_=(void*)next_;
419 obj->back_=(void*)prev_;
426 //! Default constructor - empty handle
429 //! Constructor that constructs from a pointer to new object
430 rhandle(pointer x):handle<T>(x)
432 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
433 if(obj)add_to_rlist();
436 rhandle(const handle<value_type> &x):handle<T>(x)
438 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
439 if(obj)add_to_rlist();
442 //! Default copy constructor
443 rhandle(const rhandle<value_type> &x):handle<T>(x)
445 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
446 if(obj)add_to_rlist();
449 //! Handle is released on deletion
450 ~rhandle() { detach(); }
452 //! Template Assignment operator
453 /*! \note This class may not be necessary, and may be removed
454 ** at some point in the future.
457 template <class U> const handle<value_type> &
458 operator=(const handle<U> &x)
465 obj=static_cast<value_type*>(x.get());
475 //! Assignment operator
476 rhandle<value_type> &
477 operator=(const rhandle<value_type> &x)
479 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
495 operator=(const handle<value_type> &x)
497 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
513 operator=(value_type* x)
515 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
530 //! Handle release procedure
531 /*! unref()'s the object and sets the internal object pointer to \c NULL */
535 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
536 if(obj)del_from_rlist();
537 handle<value_type>::detach();
541 // This will be reintroduced with a new function
542 //void release() { detach(); }
544 void reset() { detach(); }
546 //! Creates a new instance of a T object and puts it in the handle.
547 /*! Uses the default constructor */
548 void spawn() { operator=(handle<value_type>(new T())); }
550 //! Returns number of reversible instances
554 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
555 return obj?obj->rcount():0;
558 //! Returns true if there is only one instance of the object
562 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
563 assert(obj); return obj->front_==obj->back_;
567 int replace(const handle<value_type> &x)
569 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
571 assert(x.get()!=obj);
576 rhandle<value_type> *iter;
577 rhandle<value_type> *next;
579 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
590 for(;iter;iter=next,next=iter?iter->next_:0,i++)
592 assert(iter->get()==obj_);
596 assert(obj==x.get());
601 //! Swaps the values of two handles without reference counts
602 /*! \warning not yet implemented. \writeme */
604 swap(handle<value_type> &x);
614 }; // END of template class rhandle
617 // ========================================================================
618 /*! \class loose_handle _handle.h ETL/handle
619 ** \brief Loose Object Handle
620 ** \see shared_object, handle
628 typedef T value_type;
629 typedef T& reference;
630 typedef const T& const_reference;
632 typedef const T* const_pointer;
633 typedef int count_type;
634 typedef int size_type;
640 value_type *obj; //!< Pointer to object
644 //! Default constructor - empty handle
645 loose_handle():obj(0) {}
647 //! Constructor that constructs from a pointer to new object
648 loose_handle(pointer x):obj(x) { }
650 //! Default copy constructor
651 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
653 loose_handle(const handle<value_type> &x):obj(x.get()) { }
655 template <class U> const loose_handle<value_type> &
656 operator=(const handle<U> &x)
661 obj=static_cast<value_type*>(x.get());
665 template <class U> const loose_handle<value_type> &
666 operator=(const loose_handle<U> &x)
671 obj=static_cast<value_type*>(x.get());
675 //! Assignment operator
676 const loose_handle<value_type> &
677 operator=(const loose_handle<value_type> &x)
686 //! Swaps the values of two handles without reference counts
687 loose_handle<value_type> &
688 swap(loose_handle<value_type> &x)
696 //! Handle release procedure
697 void detach() { obj=0; }
699 // This will be reintroduced with a new function
700 //void release() { detach(); }
702 void reset() { detach(); }
704 bool empty()const { return obj==0; }
706 handle<value_type> clone()const { assert(obj); return obj->clone(); }
708 //! Returns a constant handle to our object
709 loose_handle<const value_type> constant()const { return *this; }
711 //! Returns number of instances
714 { return obj?obj->count():0; }
718 { assert(obj); return *obj; }
722 { assert(obj); return obj; }
724 //! static_cast<> overload
726 //operator loose_handle<U>()const
727 //{ return loose_handle<U>(static_cast<U*>(obj)); }
729 //! static_cast<> overload (for consts)
730 operator loose_handle<const value_type>()const
731 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
733 operator handle<value_type>()const
734 { return handle<value_type>(obj); }
736 operator rhandle<value_type>()const
737 { return rhandle<value_type>(obj); }
739 //! Returns pointer to the object that is being wrapped
740 pointer get()const { return obj; }
742 //! More explicit bool cast
750 void ref() { if(obj)obj->ref(); }
752 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
753 }; // END of template class loose_handle
755 // cast loose_handle<> -> handle<>
756 template <class T> template <class U> handle<T> handle<T>::cast_static (const loose_handle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
757 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const loose_handle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
758 template <class T> template <class U> handle<T> handle<T>::cast_const (const loose_handle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
759 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const loose_handle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
761 // cast rhandle_handle<> -> handle<>
762 template <class T> template <class U> handle<T> handle<T>::cast_static (const rhandle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
763 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const rhandle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
764 template <class T> template <class U> handle<T> handle<T>::cast_const (const rhandle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
765 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
767 // cast U* -> handle<>
768 template <class T> template <class U> handle<T> handle<T>::cast_static (U* x) { return handle<T>(static_cast <T*>(x)); }
769 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (U* x) { return handle<T>(dynamic_cast <T*>(x)); }
770 template <class T> template <class U> handle<T> handle<T>::cast_const (U* x) { return handle<T>(const_cast <T*>(x)); }
771 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U* x) { return handle<T>(reinterpret_cast<T*>(x)); }
773 // operator== for handle<>, loose_handle<> and T*
774 template <class T,class U> bool operator==(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
775 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
776 template <class T,class U> bool operator==(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
777 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
778 template <class T> bool operator==(const handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
779 template <class T> bool operator==(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
780 template <class T> bool operator==(const T* lhs,const handle<T>& rhs) { return (lhs ==rhs.get()); }
781 template <class T> bool operator==(const T* lhs,const loose_handle<T>& rhs) { return (lhs ==rhs.get()); }
783 // operator!= for handle<>, loose_handle<> and T*
784 template <class T,class U> bool operator!=(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
785 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
786 template <class T,class U> bool operator!=(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
787 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
788 template <class T> bool operator!=(const handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
789 template <class T> bool operator!=(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
790 template <class T> bool operator!=(const T* lhs,const handle<T>& rhs) { return (lhs !=rhs.get()); }
791 template <class T> bool operator!=(const T* lhs,const loose_handle<T>& rhs) { return (lhs !=rhs.get()); }
793 // operator< for handle<>, loose_handle<> and T*
794 template <class T,class U> bool operator<(const handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
795 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
796 template <class T,class U> bool operator<(const handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
797 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
798 template <class T> bool operator<(const handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
799 template <class T> bool operator<(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
800 template <class T> bool operator<(const T* lhs,const handle<T>& rhs) { return (lhs <rhs.get()); }
801 template <class T> bool operator<(const T* lhs,const loose_handle<T>& rhs) { return (lhs <rhs.get()); }
805 /* === E N D =============================================================== */