include/xot/ref.h in xot-0.1.6 vs include/xot/ref.h in xot-0.1.7

- old
+ new

@@ -2,14 +2,22 @@ #pragma once #ifndef __XOT_REF_H__ #define __XOT_REF_H__ +#ifdef check // by OSX's AssertMacros.h +#undef check +#endif + +#include <limits.h> #include <assert.h> #include <typeinfo> #include <boost/noncopyable.hpp> +#include <boost/type_traits.hpp> +#include <boost/utility/enable_if.hpp> #include <xot/defs.h> +#include <xot/exception.h> #include <xot/debug.h> //#define XOT_REF_DEBUG 1 @@ -20,90 +28,123 @@ class EmptyClass {}; template <typename SuperClass = EmptyClass> - class RefCountable : public SuperClass + class RefCountable : public SuperClass, public boost::noncopyable { public: - virtual void retain () + virtual void retain (void* data = NULL) const { - reference(+1); + refc_update_count(+1); #ifdef XOT_REF_DEBUG doutln( "%s: %d -> %d", - typeid(this).name(), count() - 1, count()); + typeid(this).name(), refc_count() - 1, refc_count()); #endif } - virtual void release () + virtual void release (void* data = NULL) const { - assert(count() >= 0); - bool del = !retained() || reference(-1) == 0; + assert(refc_count() >= 0); + bool del = !refc_retained() || refc_update_count(-1) == 0; #ifdef XOT_REF_DEBUG doutln( "%s: %d -> %d, refcount:%s, delete:%s", - typeid(this).name(), count() + 1, count(), - retained() ? "yes" : "no", del ? "yes" : "no"); + typeid(this).name(), refc_count() + 1, refc_count(), + refc_retained() ? "yes" : "no", del ? "yes" : "no"); #endif if (del) delete this; } protected: RefCountable () - : refcount(0) { } virtual ~RefCountable () { } - private: + virtual int refc_count () const + { + return refc.count; + } - int refcount; + virtual bool refc_retained () const + { + return refc.aux & 0x1; + } - bool retained () const + virtual int refc_update_count (int add) const { - return refcount & 0x1; + assert(add != 0); + if (add >= 0) refc.aux |= 0x1;// bit for retained flag. + + int c = refc.count + add; + if (c < 0) + invalid_state_error(__FILE__, __LINE__); + if (c > USHRT_MAX) + xot_error(__FILE__, __LINE__, "refc.count overflow."); + + return refc.count = c; } - int count () const + virtual ushort refc_aux () const { - return refcount >> 1; + return refc.aux >> 1; } - int reference (int add) + virtual void refc_set_aux (ushort aux) const { - assert(add != 0); - int c = count() + add; - refcount = c << 1 | 0x1;// bit for retained flag. - return c; + if ((0x1 << 15) & aux) + argument_error(__FILE__, __LINE__); + + refc.aux = (refc.aux & 0x1) | (aux << 1); } - RefCountable (const RefCountable&); + private: - RefCountable& operator = (const RefCountable&); + mutable struct Data + { + ushort count, aux; + + Data () : count(0), aux(0) {} + + } refc; + };// RefCountable - template <typename T> + template <typename T, typename = void> class Ref { typedef Ref<T> This; + typedef T Value; + + typedef const T ConstValue; + + typedef T& Reference; + + typedef const T& ConstReference; + + typedef T* Pointer; + + typedef const T* ConstPointer; + public: - Ref (T* ptr = NULL) + Ref (Pointer ptr = NULL) : ptr(ptr) { if (ptr) ptr->retain(); } @@ -111,17 +152,17 @@ : ptr(obj.ptr) { if (ptr) ptr->retain(); } - Ref& operator = (T* ptr) + This& operator = (Pointer ptr) { reset(ptr); return *this; } - Ref& operator = (const This& obj) + This& operator = (const This& obj) { if (&obj == this) return *this; reset(obj.ptr); return *this; } @@ -129,52 +170,141 @@ ~Ref () { if (ptr) ptr->release(); } - void reset (T* ptr = NULL) + void reset (Pointer ptr = NULL) { if (this->ptr == ptr) return; if (this->ptr) this->ptr->release(); this->ptr = ptr; if (this->ptr) this->ptr->retain(); } - T* get () {return ptr;} + Pointer get () {return ptr;} - const T* get () const {return ptr;} + ConstPointer get () const {return ptr;} - T* operator -> () {return get();} + Pointer operator -> () {return get();} - const T* operator -> () const {return get();} + ConstPointer operator -> () const {return get();} - T& operator * () {return *get();} + Reference operator * () {return *get();} - const T& operator * () const {return *get();} + ConstReference operator * () const {return *get();} - operator T* () {return get();} + operator Pointer () {return get();} - operator const T* () const {return get();} + operator ConstPointer () const {return get();} - bool operator == (T* ptr) const {return this->ptr == ptr;} + bool operator == (Pointer ptr) const {return this->ptr == ptr;} - bool operator != (T* ptr) const {return !operator==(ptr);} + bool operator != (Pointer ptr) const {return !operator==(ptr);} - bool operator == (const T* ptr) const {return this->ptr == ptr;} + bool operator == (ConstPointer ptr) const {return this->ptr == ptr;} - bool operator != (const T* ptr) const {return !operator==(ptr);} + bool operator != (ConstPointer ptr) const {return !operator==(ptr);} bool operator == (const This& obj) const {return ptr == obj.ptr;} bool operator != (const This& obj) const {return !operator==(obj);} + bool operator < (const This& obj) const {return ptr < obj.ptr;} + operator bool () const {return ptr != NULL;} bool operator ! () const {return !operator bool();} private: - T* ptr; + Pointer ptr; + + };// Ref + + + template <typename T> + class Ref<T, typename boost::enable_if<boost::is_const<T> >::type> + { + + typedef Ref<T> This; + + typedef typename boost::remove_const<T>::type Value; + + typedef T ConstValue; + + typedef Value& Reference; + + typedef const Value& ConstReference; + + typedef Value* Pointer; + + typedef const Value* ConstPointer; + + public: + + Ref (ConstPointer ptr = NULL) + : ptr(ptr) + { + if (ptr) ptr->retain(); + } + + Ref (const This& obj) + : ptr(obj.ptr) + { + if (ptr) ptr->retain(); + } + + This& operator = (ConstPointer ptr) + { + reset(ptr); + return *this; + } + + This& operator = (const This& obj) + { + if (&obj == this) return *this; + reset(obj.ptr); + return *this; + } + + ~Ref () + { + if (ptr) ptr->release(); + } + + void reset (ConstPointer ptr = NULL) + { + if (this->ptr == ptr) return; + if (this->ptr) this->ptr->release(); + this->ptr = ptr; + if (this->ptr) this->ptr->retain(); + } + + ConstPointer get () const {return ptr;} + + ConstPointer operator -> () const {return get();} + + ConstReference operator * () const {return *get();} + + operator ConstPointer () const {return get();} + + bool operator == (ConstPointer ptr) const {return this->ptr == ptr;} + + bool operator != (ConstPointer ptr) const {return !operator==(ptr);} + + bool operator == (const This& obj) const {return ptr == obj.ptr;} + + bool operator != (const This& obj) const {return !operator==(obj);} + + bool operator < (const This& obj) const {return ptr < obj.ptr;} + + operator bool () const {return ptr != NULL;} + + bool operator ! () const {return !operator bool();} + + private: + + ConstPointer ptr; };// Ref }// Xot