X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=ETL%2FETL%2F_smart_ptr.h;fp=ETL%2FETL%2F_smart_ptr.h;h=a34b8dda4f44d0eae5adce5fd4d8ccbc7dd64e1c;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/ETL/ETL/_smart_ptr.h b/ETL/ETL/_smart_ptr.h new file mode 100644 index 0000000..a34b8dd --- /dev/null +++ b/ETL/ETL/_smart_ptr.h @@ -0,0 +1,363 @@ +/* ======================================================================== +** Extended Template and Library +** Template Smart Pointer Implementation +** $Id$ +** +** Copyright (c) 2002 Robert B. Quattlebaum Jr. +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** === N O T E S =========================================================== +** +** This is an internal header file, included by other ETL headers. +** You should not attempt to use it directly. +** +** ========================================================================= */ + +/* === S T A R T =========================================================== */ + +#ifndef __ETL__SMART_PTR_H +#define __ETL__SMART_PTR_H + +/* === H E A D E R S ======================================================= */ + +#include +#include "_ref_count.h" + +/* === M A C R O S ========================================================= */ + +/* === T Y P E D E F S ===================================================== */ + +/* === C L A S S E S & S T R U C T S ======================================= */ + +_ETL_BEGIN_NAMESPACE + +template +struct generic_deleter +{ + void operator()(T* x)const { delete x; } +}; + +template +struct array_deleter +{ + void operator()(T* x)const { delete [] x; } +}; + +// ======================================================================== +/*! \class smart_ptr _smart_ptr.h ETL/smart_ptr +** \brief Object Smart Pointer +** \see loose_smart_ptr +** \writeme +*/ +template > +class smart_ptr +{ +public: + + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef int count_type; + typedef int size_type; + typedef D destructor_type; + +#ifdef DOXYGEN_SHOULD_SKIP_THIS // #ifdef is not a typo +private: +#endif + value_type *obj; //!< \internal Pointer to object + reference_counter refcount; + +public: + // Private constructor for convenience + smart_ptr(value_type* obj,reference_counter refcount):obj(obj),refcount(refcount) { } + + //! Default constructor - empty smart_ptr + smart_ptr():obj(0),refcount(false) {} + + //! Constructor that constructs from a pointer to new object + /*! A new smart_ptr is created with a pointer + to a newly allocated object. We need + to be explicit with this so we don't + accidently have two smart_ptrs for one + object -- that would be bad. */ + explicit smart_ptr(value_type* x):obj(x),refcount(x?true:false) { } + + //! Template copy constructor + /*! This template constructor allows us to cast + smart_ptrs much like we would pointers. */ +#ifdef _WIN32 + template + smart_ptr(const smart_ptr &x):obj((pointer)&*x.obj),refcount(x.refcount()) + { } +#endif + + //! Default copy constructor + /*! The template above is not good enough + for all compilers. We need to explicitly + define the copy constructor for this + class to work on those compilers. */ + smart_ptr(const smart_ptr &x):obj(x.obj),refcount(x.refcount) { } + + explicit smart_ptr(const value_type &x):obj(new value_type(x)) { } + + //! smart_ptr is released on deletion + ~smart_ptr() { if(refcount.unique()) destructor_type()(obj); } + + //! Template Assignment operator + template const smart_ptr & + operator=(const smart_ptr &x) + { + if(x.get()==obj) + return *this; + + reset(); + + if(x.obj) + { + obj=(pointer)x.get(); + refcount=x.refcount; + } + + return *this; + } + + //! Assignment operator + const smart_ptr & + operator=(const smart_ptr &x) + { + if(x.get()==obj) + return *this; + + reset(); + + if(x.obj) + { + + obj=(pointer)x.get(); + refcount=x.refcount; + } + + return *this; + } + + //! smart_ptr reset procedure + void + reset() + { + if(obj) + { + if(refcount.unique()) destructor_type()(obj); + refcount.detach(); + obj=0; + } + } + + void spawn() { operator=(smart_ptr(new T)); } + + //! Returns number of instances + const count_type& count()const { return refcount; } + + //! Returns true if there is only one instance of the object + bool unique()const { return refcount.unique(); } + + //! Returns a constant handle to our object + smart_ptr constant() { return *this; } + + reference operator*()const { assert(obj); return *obj; } + + pointer operator->()const { assert(obj); return obj; } + + + operator smart_ptr()const + { return smart_ptr(static_cast(obj)); } + + //! static_cast<> wrapper + template static + smart_ptr cast_static(const smart_ptr &x) + { if(!x)return NULL; return smart_ptr(static_cast(x.get()),x.refcount); } + + //! dynamic_cast<> wrapper + template static + smart_ptr cast_dynamic(const smart_ptr &x) + { if(!x)return 0; return smart_ptr(dynamic_cast(x.get()),x.refcount); } + + //! const_cast<> wrapper + template static + smart_ptr cast_const(const smart_ptr &x) + { if(!x)return 0; return smart_ptr(const_cast(x.get()),x.refcount); } + + pointer get()const { return obj; } + + //! More explicit bool cast + operator bool()const { return obj!=0; } + + bool operator!()const { return !obj; } + + //! Overloaded cast operator -- useful for implicit casts + template + operator smart_ptr() + { + // This next line should provide a syntax check + // to make sure that this cast makes sense. + // If it doesn't, this should have a compiler error. + // Otherwise, it should get optimized right out + // of the code. + //(U*)obj; + + return *reinterpret_cast*>(this); + } + +}; // END of template class smart_ptr + +// ======================================================================== +/*! \class loose_smart_ptr _smart_ptr.h ETL/smart_ptr +** \brief Loose Object Smart Pointer +** \see smart_ptr +** \writeme +*/ +template +class loose_smart_ptr +{ +public: + + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef int count_type; + typedef int size_type; + +private: + value_type *obj; //!< \internal Pointer to object + weak_reference_counter refcount; //!< \internal Pointer to object's reference counter + +public: + + //! Default constructor - empty smart_ptr + loose_smart_ptr():obj(0),refcount(0) {} + + //! Default copy constructor + loose_smart_ptr(const loose_smart_ptr &x):obj(x.get()),refcount(x.refcount) { } + + loose_smart_ptr(const smart_ptr &x):obj(x.get()),refcount(x.refcount) { } + + void reset() { obj=0,refcount=0; } + + operator smart_ptr() + { + return smart_ptr(static_cast(obj),refcount); + } + + operator smart_ptr() + { + return smart_ptr(static_cast(obj),refcount); + } + + //! Returns number of instances + const count_type& count()const { return refcount; } + + bool unique()const { return refcount.unique(); } + + reference operator*()const { assert(obj); return *obj; } + + pointer operator->()const { assert(obj); return obj; } + + pointer get()const { return obj; } + + bool operator!()const { return !obj; } +}; + +template bool +operator==(const smart_ptr &lhs,const smart_ptr &rhs) + { return (lhs.get()==rhs.get()); } +template bool +operator==(const loose_smart_ptr &lhs,const loose_smart_ptr &rhs) + { return (lhs.get()==rhs.get()); } +template bool +operator==(const smart_ptr &lhs,const loose_smart_ptr &rhs) + { return (lhs.get()==rhs.get()); } +template bool +operator==(const loose_smart_ptr &lhs,const smart_ptr &rhs) + { return (lhs.get()==rhs.get()); } +template bool +operator==(const smart_ptr &lhs,const T *rhs) + { return (lhs.get()==rhs); } +template bool +operator==(const loose_smart_ptr &lhs,const T *rhs) + { return (lhs.get()==rhs); } +template bool +operator==(const T *lhs,const smart_ptr &rhs) + { return (lhs==rhs.get()); } +template bool +operator==(const T *lhs,const loose_smart_ptr &rhs) + { return (lhs==rhs.get()); } + + +template bool +operator!=(const smart_ptr &lhs,const smart_ptr &rhs) + { return (lhs.get()!=rhs.get()); } +template bool +operator!=(const loose_smart_ptr &lhs,const loose_smart_ptr &rhs) + { return (lhs.get()!=rhs.get()); } +template bool +operator!=(const smart_ptr &lhs,const loose_smart_ptr &rhs) + { return (lhs.get()!=rhs.get()); } +template bool +operator!=(const loose_smart_ptr &lhs,const smart_ptr &rhs) + { return (lhs.get()!=rhs.get()); } +template bool +operator!=(const smart_ptr &lhs,const T *rhs) + { return (lhs.get()!=rhs); } +template bool +operator!=(const loose_smart_ptr &lhs,const T *rhs) + { return (lhs.get()!=rhs); } +template bool +operator!=(const T *lhs,const smart_ptr &rhs) + { return (lhs!=rhs.get()); } +template bool +operator!=(const T *lhs,const loose_smart_ptr &rhs) + { return (lhs!=rhs.get()); } + + +template bool +operator<(const smart_ptr &lhs,const smart_ptr &rhs) + { return (lhs.get() bool +operator<(const loose_smart_ptr &lhs,const loose_smart_ptr &rhs) + { return (lhs.get() bool +operator<(const smart_ptr &lhs,const loose_smart_ptr &rhs) + { return (lhs.get() bool +operator<(const loose_smart_ptr &lhs,const smart_ptr &rhs) + { return (lhs.get() bool +operator<(const smart_ptr &lhs,const T *rhs) + { return (lhs.get() bool +operator<(const loose_smart_ptr &lhs,const T *rhs) + { return (lhs.get() bool +operator<(const T *lhs,const smart_ptr &rhs) + { return (lhs bool +operator<(const T *lhs,const loose_smart_ptr &rhs) + { return (lhs