1 /* === E T L =============================================================== */
4 ** \brief Template Object Handle Implementation
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 ** Copyright (c) 2007 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
23 ** This is an internal header file, included by other ETL headers.
24 ** You should not attempt to use it directly.
26 /* ========================================================================= */
28 /* === S T A R T =========================================================== */
30 #ifndef __ETL__HANDLE_H
31 #define __ETL__HANDLE_H
33 /* === H E A D E R S ======================================================= */
37 /* === M A C R O S ========================================================= */
39 /* === T Y P E D E F S ===================================================== */
41 #define ETL_SELF_DELETING_SHARED_OBJECT
43 /* === C L A S S E S & S T R U C T S ======================================= */
46 #define assert_cast static_cast
48 #define assert_cast dynamic_cast
54 // Forward Declarations
55 template <class T> class handle;
56 template <class T> class loose_handle;
57 template <class T> class rhandle;
60 // ========================================================================
61 /*! \class shared_object _handle.h ETL/handle
62 ** \brief Shared Object Base Class
63 ** \see handle, loose_handle
72 shared_object():refcount(0) { }
74 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
75 virtual ~shared_object() { }
82 { assert(refcount>=0); refcount++; }
84 //! Returns \c false if object needs to be deleted
92 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
104 }; // END of class shared_object
106 // ========================================================================
107 /*! \class virtual_shared_object _handle.h ETL/handle
108 ** \brief Virtual Shared Object Base Class
109 ** \see handle, loose_handle
112 class virtual_shared_object
115 virtual_shared_object() { }
117 virtual ~virtual_shared_object()=0;
118 virtual void ref()const=0;
119 virtual bool unref()const=0;
120 virtual int count()const=0;
121 virtual virtual_shared_object *clone()=0;
122 }; // END of class virtual_shared_object
124 // ========================================================================
125 /*! \class handle _handle.h ETL/handle
126 ** \brief Object Handle
127 ** \see shared_object, loose_handle
135 typedef T value_type;
136 typedef T& reference;
137 typedef const T& const_reference;
139 typedef const T* const_pointer;
140 typedef int count_type;
141 typedef int size_type;
147 value_type *obj; //!< Pointer to object
151 //! Default constructor - empty handle
152 handle():obj(NULL) {}
154 //! Constructor that constructs from a pointer to new object
155 handle(pointer x):obj(x)
161 //! Default copy constructor
162 handle(const handle<value_type> &x):obj(x.get())
168 //! Handle is released on deletion
169 ~handle() { detach(); }
171 //! Template Assignment operator
172 /*! \note This class may not be necessary, and may be removed
173 ** at some point in the future.
176 template <class U> handle<value_type> &
177 operator=(const handle<U> &x)
184 obj=static_cast<value_type*>(x.get());
190 //! Assignment operator
192 operator=(const handle<value_type> &x)
204 //! Swaps the values of two handles without reference counts
206 swap(handle<value_type> &x)
214 //! Handle detach procedure
215 /*! unref()'s the object and sets the internal object pointer to \c NULL */
221 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
225 if(xobj && !xobj->unref())
230 // This will be reintroduced with a new function
231 //void release() { detach(); }
233 void reset() { detach(); }
235 bool empty()const { return obj==0; }
237 //! Creates a new instance of a T object and puts it in the handle.
238 /*! Uses the default constructor */
239 void spawn() { operator=(handle(new T())); }
241 handle<value_type> clone()const { assert(obj); return static_cast<value_type*>(obj->clone()); }
243 //! Returns a constant handle to our object
244 handle<const value_type> constant()const { assert(obj); return *this; }
246 //! Returns number of instances
249 { return obj?obj->count():0; }
251 //! Returns true if there is only one instance of the object
254 { assert(obj); return count()==1; }
258 { assert(obj); return *obj; }
262 { assert(obj); return obj; }
264 //! More explicit bool cast
266 { return obj!=NULL; }
268 operator handle<const value_type>()const
269 { return handle<const value_type>(static_cast<const_pointer>(obj)); }
271 //! <tt> static_cast\<\> </tt> wrapper
272 template <class U> static handle<T> cast_static (const handle<U> &x) { return handle<T>(static_cast <T*>(x.get())); }
273 //! <tt> dynamic_cast\<\> </tt> wrapper
274 template <class U> static handle<T> cast_dynamic (const handle<U> &x) { return handle<T>(dynamic_cast <T*>(x.get())); }
275 //! <tt> const_cast\<\> </tt> wrapper
276 template <class U> static handle<T> cast_const (const handle<U> &x) { return handle<T>(const_cast <T*>(x.get())); }
277 //! <tt> reinterpret_cast\<\> </tt> wrapper
278 template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
280 template <class U> static handle<T> cast_static (const loose_handle<U> &x);
281 template <class U> static handle<T> cast_dynamic (const loose_handle<U> &x);
282 template <class U> static handle<T> cast_const (const loose_handle<U> &x);
283 template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
285 template <class U> static handle<T> cast_static (const rhandle<U> &x);
286 template <class U> static handle<T> cast_dynamic (const rhandle<U> &x);
287 template <class U> static handle<T> cast_const (const rhandle<U> &x);
288 template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
290 template <class U> static handle<T> cast_static (U* x);
291 template <class U> static handle<T> cast_dynamic (U* x);
292 template <class U> static handle<T> cast_const (U* x);
293 template <class U> static handle<T> cast_reinterpret(U* x);
295 //! Returns pointer to the object that is being wrapped
296 pointer get()const { return obj; }
302 //! static_cast<> overload -- Useful for implicit casts
304 operator handle<U>()const
305 { return handle<U>(static_cast<U*>(obj)); }
306 }; // END of template class handle
308 // ========================================================================
309 /*! \class rshared_object _handle.h ETL/handle
310 ** \brief Replaceable Shared Object Base Class
314 class rshared_object : public shared_object
317 mutable int rrefcount;
324 rshared_object():rrefcount(0),front_(0),back_(0) { }
337 { return rrefcount; }
338 }; // END of class rshared_object
340 // ========================================================================
341 /*! \class rhandle _handle.h ETL/handle
342 ** \brief Replaceable Object Handle
343 ** \see rshared_object, handle, loose_handle
347 class rhandle : public handle<T>
349 friend class rshared_object;
352 typedef T value_type;
353 typedef T& reference;
354 typedef const T& const_reference;
356 typedef const T* const_pointer;
357 typedef int count_type;
358 typedef int size_type;
361 using handle<value_type>::count;
362 using handle<value_type>::unique;
363 using handle<value_type>::operator bool;
364 using handle<value_type>::get;
365 using handle<value_type>::operator*;
366 using handle<value_type>::operator->;
369 operator const handle<value_type>&()const
374 using handle<value_type>::obj;
376 rhandle<value_type> *prev_;
377 rhandle<value_type> *next_;
381 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
386 // If this is the first reversible handle
389 obj->front_=obj->back_=this;
394 prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
400 void del_from_rlist()
402 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
406 // If this is the last reversible handle
407 if(obj->front_==obj->back_)
409 obj->front_=obj->back_=0;
415 obj->front_=(void*)next_;
420 obj->back_=(void*)prev_;
427 //! Default constructor - empty handle
430 //! Constructor that constructs from a pointer to new object
431 rhandle(pointer x):handle<T>(x)
433 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
434 if(obj)add_to_rlist();
437 rhandle(const handle<value_type> &x):handle<T>(x)
439 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
440 if(obj)add_to_rlist();
443 //! Default copy constructor
444 rhandle(const rhandle<value_type> &x):handle<T>(x)
446 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
447 if(obj)add_to_rlist();
450 //! Handle is released on deletion
451 ~rhandle() { detach(); }
453 //! Template Assignment operator
454 /*! \note This class may not be necessary, and may be removed
455 ** at some point in the future.
458 template <class U> const handle<value_type> &
459 operator=(const handle<U> &x)
466 obj=static_cast<value_type*>(x.get());
476 //! Assignment operator
477 rhandle<value_type> &
478 operator=(const rhandle<value_type> &x)
480 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
496 operator=(const handle<value_type> &x)
498 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
514 operator=(value_type* x)
516 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
531 //! Handle release procedure
532 /*! unref()'s the object and sets the internal object pointer to \c NULL */
536 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
537 if(obj)del_from_rlist();
538 handle<value_type>::detach();
542 // This will be reintroduced with a new function
543 //void release() { detach(); }
545 void reset() { detach(); }
547 //! Creates a new instance of a T object and puts it in the handle.
548 /*! Uses the default constructor */
549 void spawn() { operator=(handle<value_type>(new T())); }
551 //! Returns number of reversible instances
555 // value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
556 return obj?obj->rcount():0;
559 //! Returns true if there is only one instance of the object
563 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
564 assert(obj); return obj->front_==obj->back_;
568 int replace(const handle<value_type> &x)
570 // value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
572 assert(x.get()!=obj);
577 rhandle<value_type> *iter;
578 rhandle<value_type> *next;
580 iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
591 for(;iter;iter=next,next=iter?iter->next_:0,i++)
593 assert(iter->get()==obj_);
597 assert(obj==x.get());
602 //! Swaps the values of two handles without reference counts
603 /*! \warning not yet implemented. \writeme */
605 swap(handle<value_type> &x);
615 }; // END of template class rhandle
618 // ========================================================================
619 /*! \class loose_handle _handle.h ETL/handle
620 ** \brief Loose Object Handle
621 ** \see shared_object, handle
629 typedef T value_type;
630 typedef T& reference;
631 typedef const T& const_reference;
633 typedef const T* const_pointer;
634 typedef int count_type;
635 typedef int size_type;
641 value_type *obj; //!< Pointer to object
645 //! Default constructor - empty handle
646 loose_handle():obj(0) {}
648 //! Constructor that constructs from a pointer to new object
649 loose_handle(pointer x):obj(x) { }
651 //! Default copy constructor
652 loose_handle(const loose_handle<value_type> &x):obj(x.get()) { }
654 loose_handle(const handle<value_type> &x):obj(x.get()) { }
656 template <class U> const loose_handle<value_type> &
657 operator=(const handle<U> &x)
662 obj=static_cast<value_type*>(x.get());
666 template <class U> const loose_handle<value_type> &
667 operator=(const loose_handle<U> &x)
672 obj=static_cast<value_type*>(x.get());
676 //! Assignment operator
677 const loose_handle<value_type> &
678 operator=(const loose_handle<value_type> &x)
687 //! Swaps the values of two handles without reference counts
688 loose_handle<value_type> &
689 swap(loose_handle<value_type> &x)
697 //! Handle release procedure
698 void detach() { obj=0; }
700 // This will be reintroduced with a new function
701 //void release() { detach(); }
703 void reset() { detach(); }
705 bool empty()const { return obj==0; }
707 handle<value_type> clone()const { assert(obj); return obj->clone(); }
709 //! Returns a constant handle to our object
710 loose_handle<const value_type> constant()const { return *this; }
712 //! Returns number of instances
715 { return obj?obj->count():0; }
719 { assert(obj); return *obj; }
723 { assert(obj); return obj; }
725 //! static_cast<> overload
727 //operator loose_handle<U>()const
728 //{ return loose_handle<U>(static_cast<U*>(obj)); }
730 //! static_cast<> overload (for consts)
731 operator loose_handle<const value_type>()const
732 { return loose_handle<const value_type>(static_cast<const_pointer>(obj)); }
734 operator handle<value_type>()const
735 { return handle<value_type>(obj); }
737 operator rhandle<value_type>()const
738 { return rhandle<value_type>(obj); }
740 //! Returns pointer to the object that is being wrapped
741 pointer get()const { return obj; }
743 //! More explicit bool cast
751 void ref() { if(obj)obj->ref(); }
753 bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
754 }; // END of template class loose_handle
756 // cast loose_handle<> -> handle<>
757 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())); }
758 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())); }
759 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())); }
760 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())); }
762 // cast rhandle_handle<> -> handle<>
763 template <class T> template <class U> handle<T> handle<T>::cast_static (const rhandle<U>& x) { return handle<T>(static_cast <T*>(x.get())); }
764 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (const rhandle<U>& x) { return handle<T>(dynamic_cast <T*>(x.get())); }
765 template <class T> template <class U> handle<T> handle<T>::cast_const (const rhandle<U>& x) { return handle<T>(const_cast <T*>(x.get())); }
766 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>& x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
768 // cast U* -> handle<>
769 template <class T> template <class U> handle<T> handle<T>::cast_static (U* x) { return handle<T>(static_cast <T*>(x)); }
770 template <class T> template <class U> handle<T> handle<T>::cast_dynamic (U* x) { return handle<T>(dynamic_cast <T*>(x)); }
771 template <class T> template <class U> handle<T> handle<T>::cast_const (U* x) { return handle<T>(const_cast <T*>(x)); }
772 template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U* x) { return handle<T>(reinterpret_cast<T*>(x)); }
774 // operator== for handle<>, loose_handle<> and T*
775 template <class T,class U> bool operator==(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
776 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
777 template <class T,class U> bool operator==(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
778 template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()==rhs.get()); }
779 template <class T> bool operator==(const handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
780 template <class T> bool operator==(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()==rhs); }
781 template <class T> bool operator==(const T* lhs,const handle<T>& rhs) { return (lhs ==rhs.get()); }
782 template <class T> bool operator==(const T* lhs,const loose_handle<T>& rhs) { return (lhs ==rhs.get()); }
784 // operator!= for handle<>, loose_handle<> and T*
785 template <class T,class U> bool operator!=(const handle <T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
786 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
787 template <class T,class U> bool operator!=(const handle <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
788 template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle <U>& rhs) { return (lhs.get()!=rhs.get()); }
789 template <class T> bool operator!=(const handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
790 template <class T> bool operator!=(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()!=rhs); }
791 template <class T> bool operator!=(const T* lhs,const handle<T>& rhs) { return (lhs !=rhs.get()); }
792 template <class T> bool operator!=(const T* lhs,const loose_handle<T>& rhs) { return (lhs !=rhs.get()); }
794 // operator< for handle<>, loose_handle<> and T*
795 template <class T,class U> bool operator<(const handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
796 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
797 template <class T,class U> bool operator<(const handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get()); }
798 template <class T,class U> bool operator<(const loose_handle<T>& lhs,const handle<U>& rhs) { return (lhs.get()<rhs.get()); }
799 template <class T> bool operator<(const handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
800 template <class T> bool operator<(const loose_handle<T>& lhs,const T* rhs) { return (lhs.get()<rhs); }
801 template <class T> bool operator<(const T* lhs,const handle<T>& rhs) { return (lhs <rhs.get()); }
802 template <class T> bool operator<(const T* lhs,const loose_handle<T>& rhs) { return (lhs <rhs.get()); }
806 /* === E N D =============================================================== */