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 from 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 from 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 from 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 from 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 from 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 from barfing
504 operator=(const handle<value_type> &x)
506 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
522 operator=(value_type* x)
524 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from 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 from 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 from 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 from 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 from 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
626 // ========================================================================
627 /*! \class loose_handle _handle.h ETL/handle
628 ** \brief Loose Object Handle
629 ** \see shared_object, handle
637 typedef T value_type;
638 typedef T& reference;
639 typedef const T& const_reference;
641 typedef const T* const_pointer;
642 typedef int count_type;
643 typedef int size_type;
646 value_type *obj; //!< Pointer to object
650 //! Default constructor - empty handle
651 loose_handle():obj(0) {}
653 //! Constructor that constructs from a pointer to new object
654 loose_handle(pointer x):obj(x) { }
656 //! Default copy constructor
657 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
659 loose_handle(const handle<value_type> &x):obj(x.get()) { }
661 template <class U> const loose_handle<value_type> &
662 operator=(const handle<U> &x)
667 obj=static_cast<value_type*>(x.get());
671 template <class U> const loose_handle<value_type> &
672 operator=(const loose_handle<U> &x)
677 obj=static_cast<value_type*>(x.get());
681 //! Assignment operator
682 const loose_handle<value_type> &
683 operator=(const loose_handle<value_type> &x)
692 //! Swaps the values of two handles without reference counts
693 loose_handle<value_type> &
694 swap(loose_handle<value_type> &x)
702 //! Handle release procedure
703 void detach() { obj=0; }
705 // This will be reintroduced with a new function
706 //void release() { detach(); }
708 void reset() { detach(); }
710 bool empty()const { return obj==0; }
712 handle<value_type> clone()const { assert(obj); return obj->clone(); }
714 //! Returns a constant handle to our object
715 loose_handle<const value_type> constant()const { return *this; }
717 //! Returns number of instances
720 { return obj?obj->count():0; }
724 { assert(obj); return *obj; }
728 { assert(obj); return obj; }
730 //! static_cast<> overload
732 //operator loose_handle<U>()const
733 //{ return loose_handle<U>(static_cast<U*>(obj)); }
735 //! static_cast<> overload (for consts)
736 operator loose_handle<const value_type>()const
737 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
739 operator handle<value_type>()const
740 { return handle<value_type>(obj); }
742 operator rhandle<value_type>()const
743 { return rhandle<value_type>(obj); }
745 //! Returns pointer to the object that is being wrapped
746 pointer get()const { return obj; }
748 //! More explicit bool cast
756 void ref() { if(obj)obj->ref(); }
758 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
759 }; // END of template class loose_handle
761 // cast loose_handle<> -> handle<>
762 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())); }
763 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())); }
764 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())); }
765 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())); }
767 // cast rhandle_handle<> -> handle<>
768 template <class T> template <class U> handle<T> handle<T>::cast_static (const rhandle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
769 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const rhandle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
770 template <class T> template <class U> handle<T> handle<T>::cast_const (const rhandle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
771 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
773 // cast U* -> handle<>
774 template <class T> template <class U> handle<T> handle<T>::cast_static (U* x) { return handle<T>(static_cast <T*>(x)); }
775 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (U* x) { return handle<T>(dynamic_cast <T*>(x)); }
776 template <class T> template <class U> handle<T> handle<T>::cast_const (U* x) { return handle<T>(const_cast <T*>(x)); }
777 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U* x) { return handle<T>(reinterpret_cast<T*>(x)); }
779 // operator== for handle<>, loose_handle<> and T*
780 template <class T,class U> bool operator==(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
781 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
782 template <class T,class U> bool operator==(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
783 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
784 template <class T> bool operator==(const handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
785 template <class T> bool operator==(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
786 template <class T> bool operator==(const T* lhs,const handle<T>& rhs) { return (lhs ==rhs.get()); }
787 template <class T> bool operator==(const T* lhs,const loose_handle<T>& rhs) { return (lhs ==rhs.get()); }
789 // operator!= for handle<>, loose_handle<> and T*
790 template <class T,class U> bool operator!=(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
791 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
792 template <class T,class U> bool operator!=(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
793 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
794 template <class T> bool operator!=(const handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
795 template <class T> bool operator!=(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
796 template <class T> bool operator!=(const T* lhs,const handle<T>& rhs) { return (lhs !=rhs.get()); }
797 template <class T> bool operator!=(const T* lhs,const loose_handle<T>& rhs) { return (lhs !=rhs.get()); }
799 // operator< for handle<>, loose_handle<> and T*
800 template <class T,class U> bool operator<(const handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
801 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
802 template <class T,class U> bool operator<(const handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
803 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
804 template <class T> bool operator<(const handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
805 template <class T> bool operator<(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
806 template <class T> bool operator<(const T* lhs,const handle<T>& rhs) { return (lhs <rhs.get()); }
807 template <class T> bool operator<(const T* lhs,const loose_handle<T>& rhs) { return (lhs <rhs.get()); }
811 /* === E N D =============================================================== */