Use etl::mutexes to lock access to reference counts.
[synfig.git] / ETL / trunk / ETL / _handle.h
index 317f6c2..862c914 100644 (file)
@@ -1,11 +1,12 @@
 /* === E T L =============================================================== */
 /*!    \file _handle.h
-**     $Id: _handle.h,v 1.1.1.1 2005/01/04 01:31:47 darco Exp $
+**     $Id$
 **     \brief Template Object Handle Implementation
 **     \internal
 **
 **     \legal
 **     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2007 Chris Moore
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
 
 /* === H E A D E R S ======================================================= */
 
+// include the next line in an attempt to increase stability
+#define ETL_LOCK_REFCOUNTS
+
 #include <cassert>
 
+#ifdef ETL_LOCK_REFCOUNTS
+#  include "_mutex_simple.h"
+#endif
+
 /* === M A C R O S ========================================================= */
 
 /* === T Y P E D E F S ===================================================== */
@@ -66,7 +74,10 @@ class shared_object
 {
 private:
        mutable int refcount;
-       
+#ifdef ETL_LOCK_REFCOUNTS
+       mutable etl::mutex mtx;
+#endif
+
 protected:
        shared_object():refcount(0) { }
 
@@ -75,31 +86,46 @@ protected:
 #else
        ~shared_object() { }
 #endif
-       
-public:        
+
+public:
        void ref()const
-               { assert(refcount>=0); refcount++; }
-       
+       {
+#ifdef ETL_LOCK_REFCOUNTS
+               etl::mutex::lock lock(mtx);
+#endif
+               assert(refcount>=0);
+               refcount++;
+       }
+
        //! Returns \c false if object needs to be deleted
        bool unref()const
        {
-               assert(refcount>0);
+               bool ret = true;
+               {
+#ifdef ETL_LOCK_REFCOUNTS
+                       etl::mutex::lock lock(mtx);
+#endif
+                       assert(refcount>0);
 
-               refcount--;
+                       refcount--;
 
-               if(refcount==0) {
+                       if(refcount==0) {
+                               ret = false;
 #ifdef ETL_SELF_DELETING_SHARED_OBJECT
-                       refcount=-666;
-                       delete this;
+                               refcount=-666;
 #endif
-                       return false;
+                       }
                }
 
-               return true;
+#ifdef ETL_SELF_DELETING_SHARED_OBJECT
+               if (!ret)
+                       delete this;
+#endif
+               return ret;
        }
-       
-       int count()const
-               { return refcount; }
+
+       int count()const { return refcount; }
+
 }; // END of class shared_object
 
 // ========================================================================
@@ -140,6 +166,9 @@ public:
        typedef int size_type;
 
 protected:
+#ifdef _DEBUG
+public:
+#endif
        value_type *obj;                //!< Pointer to object
 
 public:
@@ -182,7 +211,7 @@ public:
                return *this;
        }
        */
-       
+
        //! Assignment operator
        handle<value_type> &
        operator=(const handle<value_type> &x)
@@ -229,7 +258,7 @@ public:
        void reset() { detach(); }
 
        bool empty()const { return obj==0; }
-       
+
        //! Creates a new instance of a T object and puts it in the handle.
        /*! Uses the default constructor */
        void spawn() { operator=(handle(new T())); }
@@ -264,41 +293,29 @@ public:
        operator handle<const value_type>()const
        { return handle<const value_type>(static_cast<const_pointer>(obj)); }
 
-
        //! <tt> static_cast\<\> </tt> wrapper
-       template <class U> static
-       handle<T> cast_static(const handle<U> &x)
-       { return handle<T>(static_cast<T*>(x.get())); }
-
+       template <class U> static handle<T> cast_static         (const handle<U> &x) { return handle<T>(static_cast             <T*>(x.get())); }
        //! <tt> dynamic_cast\<\> </tt> wrapper
-       template <class U> static
-       handle<T> cast_dynamic(const handle<U> &x)
-       { return handle<T>(dynamic_cast<T*>(x.get())); }
-
+       template <class U> static handle<T> cast_dynamic        (const handle<U> &x) { return handle<T>(dynamic_cast    <T*>(x.get())); }
        //! <tt> const_cast\<\> </tt> wrapper
-       template <class U> static
-       handle<T> cast_const(const handle<U> &x)
-       { return handle<T>(const_cast<T*>(x.get())); }
-
+       template <class U> static handle<T> cast_const          (const handle<U> &x) { return handle<T>(const_cast              <T*>(x.get())); }
        //! <tt> reinterpret_cast\<\> </tt> wrapper
-       template <class U> static
-       handle<T> cast_reinterpret(const handle<U> &x)
-       { return handle<T>(reinterpret_cast<T*>(x.get())); }
+       template <class U> static handle<T> cast_reinterpret(const handle<U> &x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
 
-       template<class U> static handle<T> cast_static(const loose_handle<U> &x);
-       template<class U> static handle<T> cast_dynamic(const loose_handle<U> &x);
-       template<class U> static handle<T> cast_const(const loose_handle<U> &x);
-       template<class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
+       template <class U> static handle<T> cast_static         (const loose_handle<U> &x);
+       template <class U> static handle<T> cast_dynamic        (const loose_handle<U> &x);
+       template <class U> static handle<T> cast_const          (const loose_handle<U> &x);
+       template <class U> static handle<T> cast_reinterpret(const loose_handle<U> &x);
 
-       template<class U> static handle<T> cast_static(const rhandle<U> &x);
-       template<class U> static handle<T> cast_dynamic(const rhandle<U> &x);
-       template<class U> static handle<T> cast_const(const rhandle<U> &x);
-       template<class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
+       template <class U> static handle<T> cast_static         (const rhandle<U> &x);
+       template <class U> static handle<T> cast_dynamic        (const rhandle<U> &x);
+       template <class U> static handle<T> cast_const          (const rhandle<U> &x);
+       template <class U> static handle<T> cast_reinterpret(const rhandle<U> &x);
 
-       template<class U> static handle<T> cast_static(U* x);
-       template<class U> static handle<T> cast_dynamic(U* x);
-       template<class U> static handle<T> cast_const(U* x);
-       template<class U> static handle<T> cast_reinterpret(U* x);
+       template <class U> static handle<T> cast_static         (U* x);
+       template <class U> static handle<T> cast_dynamic        (U* x);
+       template <class U> static handle<T> cast_const          (U* x);
+       template <class U> static handle<T> cast_reinterpret(U* x);
 
        //! Returns pointer to the object that is being wrapped
        pointer get()const { return obj; }
@@ -327,20 +344,20 @@ private:
 public:
        void *front_;
        void *back_;
-       
+
 protected:
        rshared_object():rrefcount(0),front_(0),back_(0) { }
-       
-public:        
+
+public:
        void rref()const
                { rrefcount++; }
-       
+
        void runref()const
        {
                assert(rrefcount>0);
                rrefcount--;
        }
-       
+
        int rcount()const
                { return rrefcount; }
 }; // END of class rshared_object
@@ -370,9 +387,9 @@ public:
        using handle<value_type>::unique;
        using handle<value_type>::operator bool;
        using handle<value_type>::get;
-       using handle<value_type>::operator *;
-       using handle<value_type>::operator ->;
-       
+       using handle<value_type>::operator*;
+       using handle<value_type>::operator->;
+
        /*
        operator const handle<value_type>&()const
        { return *this; }
@@ -380,25 +397,25 @@ public:
 
 private:
        using handle<value_type>::obj;
-       
+
        rhandle<value_type> *prev_;
        rhandle<value_type> *next_;
 
        void add_to_rlist()
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
 
                assert(obj);
                obj->rref();
 
-               // If this is the first reversable handle
+               // If this is the first reversible handle
                if(!obj->front_)
                {
                        obj->front_=obj->back_=this;
                        prev_=next_=0;
                        return;
                }
-               
+
                prev_=reinterpret_cast<rhandle<value_type>*>(obj->back_);
                next_=0;
                prev_->next_=this;
@@ -407,11 +424,11 @@ private:
 
        void del_from_rlist()
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                assert(obj);
                obj->runref();
 
-               // If this is the last reversable handle
+               // If this is the last reversible handle
                if(obj->front_==obj->back_)
                {
                        obj->front_=obj->back_=0;
@@ -429,7 +446,7 @@ private:
                else
                        next_->prev_=prev_;
        }
-       
+
 public:
 
        //! Default constructor - empty handle
@@ -438,26 +455,26 @@ public:
        //! Constructor that constructs from a pointer to new object
        rhandle(pointer x):handle<T>(x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(obj)add_to_rlist();
        }
 
        rhandle(const handle<value_type> &x):handle<T>(x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(obj)add_to_rlist();
        }
 
        //! Default copy constructor
        rhandle(const rhandle<value_type> &x):handle<T>(x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(obj)add_to_rlist();
        }
 
        //! Handle is released on deletion
        ~rhandle() { detach(); }
-               
+
        //! Template Assignment operator
        /*! \note This class may not be necessary, and may be removed
        **              at some point in the future.
@@ -480,12 +497,12 @@ public:
                return *this;
        }
        */
-       
+
        //! Assignment operator
        rhandle<value_type> &
        operator=(const rhandle<value_type> &x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(x.get()==obj)
                        return *this;
 
@@ -503,7 +520,7 @@ public:
        rhandle<value_type>&
        operator=(const handle<value_type> &x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(x.get()==obj)
                        return *this;
 
@@ -521,7 +538,7 @@ public:
        rhandle<value_type>&
        operator=(value_type* x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(x==obj)
                        return *this;
 
@@ -541,7 +558,7 @@ public:
        void
        detach()
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                if(obj)del_from_rlist();
                handle<value_type>::detach();
                obj=0;
@@ -556,11 +573,11 @@ public:
        /*! Uses the default constructor */
        void spawn() { operator=(handle<value_type>(new T())); }
 
-       //! Returns number of reversable instances
+       //! Returns number of reversible instances
        count_type
        rcount()const
        {
-//             value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*const& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                return obj?obj->rcount():0;
        }
 
@@ -568,42 +585,42 @@ public:
        bool
        runique()const
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                assert(obj); return obj->front_==obj->back_;
        }
 
        //! \writeme
        int replace(const handle<value_type> &x)
        {
-//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 form barfing
+//             value_type*& obj(handle<T>::obj); // Required to keep gcc 3.4.2 from barfing
                assert(obj);
                assert(x.get()!=obj);
-               
+
                if(x.get()==obj)
                        return 0;
-               
+
                rhandle<value_type> *iter;
                rhandle<value_type> *next;
-               
+
                iter=reinterpret_cast<rhandle<value_type>*>(obj->front_);
 
-               assert(iter);           
+               assert(iter);
 
                next=iter->next_;
-               
+
                int i=0;
                #ifndef NDEBUG
                pointer obj_=obj;
                #endif
-               
+
                for(;iter;iter=next,next=iter?iter->next_:0,i++)
                {
-                       assert(iter->get()==obj_);      
+                       assert(iter->get()==obj_);
                        (*iter)=x;
                }
 
                assert(obj==x.get());
-               
+
                return i;
        }
 
@@ -623,11 +640,6 @@ public:
 }; // END of template class rhandle
 
 
-
-
-
-
-
 // ========================================================================
 /*!    \class  loose_handle _handle.h  ETL/handle
 **     \brief  Loose Object Handle
@@ -648,6 +660,9 @@ public:
        typedef int size_type;
 
 protected:
+#ifdef _DEBUG
+public:
+#endif
        value_type *obj;                //!< Pointer to object
 
 public:
@@ -711,7 +726,7 @@ public:
        //void release() { detach(); }
 
        void reset() { detach(); }
-       
+
        bool empty()const { return obj==0; }
 
        handle<value_type> clone()const { assert(obj); return obj->clone(); }
@@ -763,141 +778,53 @@ public:
        bool unref() { if(obj && !obj->unref()){ obj=0; return false; } return true; }
 }; // END of template class loose_handle
 
-
-
-
-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())); }
-
-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())); }
-
-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())); }
-
-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())); }
-
-       
-       
-template <class T> template <class U> handle<T>
-handle<T>::cast_static(const rhandle<U> &x)
-       { return handle<T>(static_cast<T*>(x.get())); }
-
-template <class T> template <class U> handle<T>
-handle<T>::cast_dynamic(const rhandle<U> &x)
-       { return handle<T>(dynamic_cast<T*>(x.get())); }
-
-template <class T> template <class U> handle<T>
-handle<T>::cast_const(const rhandle<U> &x)
-       { return handle<T>(const_cast<T*>(x.get())); }
-
-template <class T> template <class U> handle<T>
-handle<T>::cast_reinterpret(const rhandle<U> &x)
-       { return handle<T>(reinterpret_cast<T*>(x.get())); }
-
-       
-       
-template <class T> template <class U> handle<T>
-handle<T>::cast_static(U* x)
-       { return handle<T>(static_cast<T*>(x)); }
-
-template <class T> template <class U> handle<T>
-handle<T>::cast_dynamic(U* x)
-       { return handle<T>(dynamic_cast<T*>(x)); }
-
-template <class T> template <class U> handle<T>
-handle<T>::cast_const(U* x)
-       { return handle<T>(const_cast<T*>(x)); }
-
-template <class T> template <class U> handle<T>
-handle<T>::cast_reinterpret(U* x)
-       { return handle<T>(reinterpret_cast<T*>(x)); }
-
-
-
-
-
-template <class T,class U> bool
-operator==(const handle<T> &lhs,const handle<U> &rhs)
-       { return (lhs.get()==rhs.get()); }
-template <class T,class U> bool
-operator==(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
-       { return (lhs.get()==rhs.get()); }
-template <class T,class U> bool
-operator==(const handle<T> &lhs,const loose_handle<U> &rhs)
-       { return (lhs.get()==rhs.get()); }
-template <class T,class U> bool
-operator==(const loose_handle<T> &lhs,const handle<U> &rhs)
-       { return (lhs.get()==rhs.get()); }
-template <class T> bool
-operator==(const handle<T> &lhs,const T *rhs)
-       { return (lhs.get()==rhs); }
-template <class T> bool
-operator==(const loose_handle<T> &lhs,const T *rhs)
-       { return (lhs.get()==rhs); }
-template <class T> bool
-operator==(const T *lhs,const handle<T> &rhs)
-       { return (lhs==rhs.get()); }
-template <class T> bool
-operator==(const T *lhs,const loose_handle<T> &rhs)
-       { return (lhs==rhs.get()); }
-
-
-template <class T,class U> bool
-operator!=(const handle<T> &lhs,const handle<U> &rhs)
-       { return (lhs.get()!=rhs.get()); }
-template <class T,class U> bool
-operator!=(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
-       { return (lhs.get()!=rhs.get()); }
-template <class T,class U> bool
-operator!=(const handle<T> &lhs,const loose_handle<U> &rhs)
-       { return (lhs.get()!=rhs.get()); }
-template <class T,class U> bool
-operator!=(const loose_handle<T> &lhs,const handle<U> &rhs)
-       { return (lhs.get()!=rhs.get()); }
-template <class T> bool
-operator!=(const handle<T> &lhs,const T *rhs)
-       { return (lhs.get()!=rhs); }
-template <class T> bool
-operator!=(const loose_handle<T> &lhs,const T *rhs)
-       { return (lhs.get()!=rhs); }
-template <class T> bool
-operator!=(const T *lhs,const handle<T> &rhs)
-       { return (lhs!=rhs.get()); }
-template <class T> bool
-operator!=(const T *lhs,const loose_handle<T> &rhs)
-       { return (lhs!=rhs.get()); }
-
-
-template <class T,class U> bool
-operator<(const handle<T> &lhs,const handle<U> &rhs)
-       { return (lhs.get()<rhs.get()); }
-template <class T,class U> bool
-operator<(const loose_handle<T> &lhs,const loose_handle<U> &rhs)
-       { return (lhs.get()<rhs.get()); }
-template <class T,class U> bool
-operator<(const handle<T> &lhs,const loose_handle<U> &rhs)
-       { return (lhs.get()<rhs.get()); }
-template <class T,class U> bool
-operator<(const loose_handle<T> &lhs,const handle<U> &rhs)
-       { return (lhs.get()<rhs.get()); }
-template <class T> bool
-operator<(const handle<T> &lhs,const T *rhs)
-       { return (lhs.get()<rhs); }
-template <class T> bool
-operator<(const loose_handle<T> &lhs,const T *rhs)
-       { return (lhs.get()<rhs); }
-template <class T> bool
-operator<(const T *lhs,const handle<T> &rhs)
-       { return (lhs<rhs.get()); }
-template <class T> bool
-operator<(const T *lhs,const loose_handle<T> &rhs)
-       { return (lhs<rhs.get()); }
+// cast loose_handle<> -> handle<>
+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())); }
+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())); }
+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())); }
+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())); }
+
+// cast rhandle_handle<> -> handle<>
+template <class T> template <class U> handle<T> handle<T>::cast_static    (const rhandle<U>&      x) { return handle<T>(static_cast     <T*>(x.get())); }
+template <class T> template <class U> handle<T> handle<T>::cast_dynamic           (const rhandle<U>&      x) { return handle<T>(dynamic_cast    <T*>(x.get())); }
+template <class T> template <class U> handle<T> handle<T>::cast_const     (const rhandle<U>&      x) { return handle<T>(const_cast              <T*>(x.get())); }
+template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(const rhandle<U>&     x) { return handle<T>(reinterpret_cast<T*>(x.get())); }
+
+// cast U* -> handle<>
+template <class T> template <class U> handle<T> handle<T>::cast_static    (U*                                     x) { return handle<T>(static_cast     <T*>(x));               }
+template <class T> template <class U> handle<T> handle<T>::cast_dynamic           (U*                                     x) { return handle<T>(dynamic_cast    <T*>(x));               }
+template <class T> template <class U> handle<T> handle<T>::cast_const     (U*                                     x) { return handle<T>(const_cast              <T*>(x));               }
+template <class T> template <class U> handle<T> handle<T>::cast_reinterpret(U*                                    x) { return handle<T>(reinterpret_cast<T*>(x));               }
+
+// operator== for handle<>, loose_handle<> and T*
+template <class T,class U> bool operator==(const handle                 <T>& lhs,const handle          <U>& rhs) { return (lhs.get()==rhs.get()); }
+template <class T,class U> bool operator==(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
+template <class T,class U> bool operator==(const handle                 <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()==rhs.get()); }
+template <class T,class U> bool operator==(const loose_handle<T>& lhs,const handle             <U>& rhs) { return (lhs.get()==rhs.get()); }
+template <class T>                bool operator==(const handle<T>&               lhs,const T*                           rhs) { return (lhs.get()==rhs);           }
+template <class T>                bool operator==(const loose_handle<T>& lhs,const T*                           rhs) { return (lhs.get()==rhs);           }
+template <class T>                bool operator==(const T*                               lhs,const handle<T>&           rhs) { return (lhs              ==rhs.get()); }
+template <class T>                bool operator==(const T*                               lhs,const loose_handle<T>& rhs) { return (lhs          ==rhs.get()); }
+
+// operator!= for handle<>, loose_handle<> and T*
+template <class T,class U> bool operator!=(const handle                 <T>& lhs,const handle          <U>& rhs) { return (lhs.get()!=rhs.get()); }
+template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
+template <class T,class U> bool operator!=(const handle                 <T>& lhs,const loose_handle<U>& rhs) { return (lhs.get()!=rhs.get()); }
+template <class T,class U> bool operator!=(const loose_handle<T>& lhs,const handle             <U>& rhs) { return (lhs.get()!=rhs.get()); }
+template <class T>                bool operator!=(const handle<T>&               lhs,const T*                           rhs) { return (lhs.get()!=rhs);           }
+template <class T>                bool operator!=(const loose_handle<T>& lhs,const T*                           rhs) { return (lhs.get()!=rhs);           }
+template <class T>                bool operator!=(const T*                               lhs,const handle<T>&           rhs) { return (lhs              !=rhs.get()); }
+template <class T>                bool operator!=(const T*                               lhs,const loose_handle<T>& rhs) { return (lhs          !=rhs.get()); }
+
+// operator< for handle<>, loose_handle<> and T*
+template <class T,class U> bool operator<(const handle<T>&               lhs,const handle<U>&           rhs) { return (lhs.get()<rhs.get());  }
+template <class T,class U> bool operator<(const loose_handle<T>&  lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get());  }
+template <class T,class U> bool operator<(const handle<T>&               lhs,const loose_handle<U>& rhs) { return (lhs.get()<rhs.get());  }
+template <class T,class U> bool operator<(const loose_handle<T>&  lhs,const handle<U>&          rhs) { return (lhs.get()<rhs.get());  }
+template <class T>                bool operator<(const handle<T>&                lhs,const T*                           rhs) { return (lhs.get()<rhs);            }
+template <class T>                bool operator<(const loose_handle<T>&  lhs,const T*                           rhs) { return (lhs.get()<rhs);            }
+template <class T>                bool operator<(const T*                                lhs,const handle<T>&           rhs) { return (lhs              <rhs.get());  }
+template <class T>                bool operator<(const T*                                lhs,const loose_handle<T>& rhs) { return (lhs          <rhs.get());  }
 
 _ETL_END_NAMESPACE