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)); }
267 //! <tt> static_cast\<\> </tt> wrapper
268 template <class U> static handle<T> cast_static (const handle<U> &x) { return handle<T>(static_cast <T*>(x.get())); }
269 //! <tt> dynamic_cast\<\> </tt> wrapper
270 template <class U> static handle<T> cast_dynamic (const handle<U> &x) { return handle<T>(dynamic_cast <T*>(x.get())); }
271 //! <tt> const_cast\<\> </tt> wrapper
272 template <class U> static handle<T> cast_const (const handle<U> &x) { return handle<T>(const_cast <T*>(x.get())); }
273 //! <tt> reinterpret_cast\<\> </tt> wrapper
274 template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
276 template <class U> static handle<T> cast_static (const loose_handle<U> &x);
277 template <class U> static handle<T> cast_dynamic (const loose_handle<U> &x);
278 template <class U> static handle<T> cast_const (const loose_handle<U> &x);
279 template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
281 template <class U> static handle<T> cast_static (const rhandle<U> &x);
282 template <class U> static handle<T> cast_dynamic (const rhandle<U> &x);
283 template <class U> static handle<T> cast_const (const rhandle<U> &x);
284 template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
286 template <class U> static handle<T> cast_static (U* x);
287 template <class U> static handle<T> cast_dynamic (U* x);
288 template <class U> static handle<T> cast_const (U* x);
289 template <class U> static handle<T> cast_reinterpret(U* x);
291 //! Returns pointer to the object that is being wrapped
292 pointer get()const { return obj; }
298 //! static_cast<> overload -- Useful for implicit casts
300 operator handle<U>()const
301 { return handle<U>(static_cast<U*>(obj)); }
302 }; // END of template class handle
304 // ========================================================================
305 /*! \class rshared_object _handle.h ETL/handle
306 ** \brief Replaceable Shared Object Base Class
310 class rshared_object : public shared_object
313 mutable int rrefcount;
320 rshared_object():rrefcount(0),front_(0),back_(0) { }
333 { return rrefcount; }
334 }; // END of class rshared_object
336 // ========================================================================
337 /*! \class rhandle _handle.h ETL/handle
338 ** \brief Replaceable Object Handle
339 ** \see rshared_object, handle, loose_handle
343 class rhandle : public handle<T>
345 friend class rshared_object;
348 typedef T value_type;
349 typedef T& reference;
350 typedef const T& const_reference;
352 typedef const T* const_pointer;
353 typedef int count_type;
354 typedef int size_type;
357 using handle<value_type>::count;
358 using handle<value_type>::unique;
359 using handle<value_type>::operator bool;
360 using handle<value_type>::get;
361 using handle<value_type>::operator *;
362 using handle<value_type>::operator ->;
365 operator const handle<value_type>&()const
370 using handle<value_type>::obj;
372 rhandle<value_type> *prev_;
373 rhandle<value_type> *next_;
377 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
382 // If this is the first reversible handle
385 obj->front_=obj->back_=this;
390 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
396 void del_from_rlist()
398 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
402 // If this is the last reversible handle
403 if(obj->front_==obj->back_)
405 obj->front_=obj->back_=0;
411 obj->front_=(void*)next_;
416 obj->back_=(void*)prev_;
423 //! Default constructor - empty handle
426 //! Constructor that constructs from a pointer to new object
427 rhandle(pointer x):handle<T>(x)
429 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
430 if(obj)add_to_rlist();
433 rhandle(const handle<value_type> &x):handle<T>(x)
435 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
436 if(obj)add_to_rlist();
439 //! Default copy constructor
440 rhandle(const rhandle<value_type> &x):handle<T>(x)
442 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
443 if(obj)add_to_rlist();
446 //! Handle is released on deletion
447 ~rhandle() { detach(); }
449 //! Template Assignment operator
450 /*! \note This class may not be necessary, and may be removed
451 ** at some point in the future.
454 template <class U> const handle<value_type> &
455 operator=(const handle<U> &x)
462 obj=static_cast<value_type*>(x.get());
472 //! Assignment operator
473 rhandle<value_type> &
474 operator=(const rhandle<value_type> &x)
476 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
492 operator=(const handle<value_type> &x)
494 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
510 operator=(value_type* x)
512 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
527 //! Handle release procedure
528 /*! unref()'s the object and sets the internal object pointer to \c NULL */
532 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
533 if(obj)del_from_rlist();
534 handle<value_type>::detach();
538 // This will be reintroduced with a new function
539 //void release() { detach(); }
541 void reset() { detach(); }
543 //! Creates a new instance of a T object and puts it in the handle.
544 /*! Uses the default constructor */
545 void spawn() { operator=(handle<value_type>(new T())); }
547 //! Returns number of reversible instances
551 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
552 return obj?obj->rcount():0;
555 //! Returns true if there is only one instance of the object
559 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
560 assert(obj); return obj->front_==obj->back_;
564 int replace(const handle<value_type> &x)
566 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
568 assert(x.get()!=obj);
573 rhandle<value_type> *iter;
574 rhandle<value_type> *next;
576 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
587 for(;iter;iter=next,next=iter?iter->next_:0,i++)
589 assert(iter->get()==obj_);
593 assert(obj==x.get());
598 //! Swaps the values of two handles without reference counts
599 /*! \warning not yet implemented. \writeme */
601 swap(handle<value_type> &x);
611 }; // END of template class rhandle
614 // ========================================================================
615 /*! \class loose_handle _handle.h ETL/handle
616 ** \brief Loose Object Handle
617 ** \see shared_object, handle
625 typedef T value_type;
626 typedef T& reference;
627 typedef const T& const_reference;
629 typedef const T* const_pointer;
630 typedef int count_type;
631 typedef int size_type;
634 value_type *obj; //!< Pointer to object
638 //! Default constructor - empty handle
639 loose_handle():obj(0) {}
641 //! Constructor that constructs from a pointer to new object
642 loose_handle(pointer x):obj(x) { }
644 //! Default copy constructor
645 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
647 loose_handle(const handle<value_type> &x):obj(x.get()) { }
649 template <class U> const loose_handle<value_type> &
650 operator=(const handle<U> &x)
655 obj=static_cast<value_type*>(x.get());
659 template <class U> const loose_handle<value_type> &
660 operator=(const loose_handle<U> &x)
665 obj=static_cast<value_type*>(x.get());
669 //! Assignment operator
670 const loose_handle<value_type> &
671 operator=(const loose_handle<value_type> &x)
680 //! Swaps the values of two handles without reference counts
681 loose_handle<value_type> &
682 swap(loose_handle<value_type> &x)
690 //! Handle release procedure
691 void detach() { obj=0; }
693 // This will be reintroduced with a new function
694 //void release() { detach(); }
696 void reset() { detach(); }
698 bool empty()const { return obj==0; }
700 handle<value_type> clone()const { assert(obj); return obj->clone(); }
702 //! Returns a constant handle to our object
703 loose_handle<const value_type> constant()const { return *this; }
705 //! Returns number of instances
708 { return obj?obj->count():0; }
712 { assert(obj); return *obj; }
716 { assert(obj); return obj; }
718 //! static_cast<> overload
720 //operator loose_handle<U>()const
721 //{ return loose_handle<U>(static_cast<U*>(obj)); }
723 //! static_cast<> overload (for consts)
724 operator loose_handle<const value_type>()const
725 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
727 operator handle<value_type>()const
728 { return handle<value_type>(obj); }
730 operator rhandle<value_type>()const
731 { return rhandle<value_type>(obj); }
733 //! Returns pointer to the object that is being wrapped
734 pointer get()const { return obj; }
736 //! More explicit bool cast
744 void ref() { if(obj)obj->ref(); }
746 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
747 }; // END of template class loose_handle
749 // cast loose_handle<> -> handle<>
750 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())); }
751 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())); }
752 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())); }
753 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())); }
755 // cast rhandle_handle<> -> handle<>
756 template <class T> template <class U> handle<T> handle<T>::cast_static (const rhandle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
757 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const rhandle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
758 template <class T> template <class U> handle<T> handle<T>::cast_const (const rhandle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
759 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
761 // cast U* -> handle<>
762 template <class T> template <class U> handle<T> handle<T>::cast_static (U* x) { return handle<T>(static_cast <T*>(x)); }
763 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (U* x) { return handle<T>(dynamic_cast <T*>(x)); }
764 template <class T> template <class U> handle<T> handle<T>::cast_const (U* x) { return handle<T>(const_cast <T*>(x)); }
765 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U* x) { return handle<T>(reinterpret_cast<T*>(x)); }
767 // operator== for handle<>, loose_handle<> and T*
768 template <class T,class U> bool operator==(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
769 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
770 template <class T,class U> bool operator==(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
771 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
772 template <class T> bool operator==(const handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
773 template <class T> bool operator==(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
774 template <class T> bool operator==(const T* lhs,const handle<T>& rhs) { return (lhs ==rhs.get()); }
775 template <class T> bool operator==(const T* lhs,const loose_handle<T>& rhs) { return (lhs ==rhs.get()); }
777 // operator!= for handle<>, loose_handle<> and T*
778 template <class T,class U> bool operator!=(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
779 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
780 template <class T,class U> bool operator!=(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
781 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
782 template <class T> bool operator!=(const handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
783 template <class T> bool operator!=(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
784 template <class T> bool operator!=(const T* lhs,const handle<T>& rhs) { return (lhs !=rhs.get()); }
785 template <class T> bool operator!=(const T* lhs,const loose_handle<T>& rhs) { return (lhs !=rhs.get()); }
787 // operator< for handle<>, loose_handle<> and T*
788 template <class T,class U> bool operator<(const handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
789 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
790 template <class T,class U> bool operator<(const handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
791 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
792 template <class T> bool operator<(const handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
793 template <class T> bool operator<(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
794 template <class T> bool operator<(const T* lhs,const handle<T>& rhs) { return (lhs <rhs.get()); }
795 template <class T> bool operator<(const T* lhs,const loose_handle<T>& rhs) { return (lhs <rhs.get()); }
799 /* === E N D =============================================================== */