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