2012-04-30 20:23:53 +02:00
|
|
|
#ifndef GLW_BOOKKEEPING_H
|
|
|
|
#define GLW_BOOKKEEPING_H
|
|
|
|
|
|
|
|
#include "./common.h"
|
|
|
|
|
|
|
|
namespace glw
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
|
2012-05-07 21:21:47 +02:00
|
|
|
struct NoType { };
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T> struct DefaultDeleter { void operator () (T * t) { delete t; } };
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 21:21:47 +02:00
|
|
|
template <typename T> struct BaseOf { typedef NoType Type; };
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T, typename B> struct RootOfType { typedef typename RootOfType<B, typename BaseOf<B>::Type>::Type Type; };
|
2012-05-07 21:21:47 +02:00
|
|
|
template <typename T> struct RootOfType<T, NoType> { typedef T Type; };
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T> struct RootOf { typedef typename RootOfType<T, typename BaseOf<T>::Type>::Type Type; };
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T, typename B> struct DeleterOfType { typedef typename DeleterOfType<B, typename BaseOf<B>::Type>::Type Type; };
|
2012-05-07 21:21:47 +02:00
|
|
|
template <typename T> struct DeleterOfType<T, NoType> { typedef DefaultDeleter<T> Type; };
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T> struct DeleterOf { typedef typename DeleterOfType<T, typename BaseOf<T>::Type>::Type Type; };
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename TObject, typename TDeleter, typename TBaseObject>
|
|
|
|
class RefCountedObject : public RefCountedObject<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type>
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
typedef RefCountedObject<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type> BaseType;
|
|
|
|
typedef RefCountedObject<TObject, TDeleter, TBaseObject> ThisType;
|
|
|
|
typedef TObject ObjectType;
|
|
|
|
typedef TDeleter DeleterType;
|
|
|
|
typedef TBaseObject BaseObjectType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
RefCountedObject(ObjectType * object, const DeleterType & deleter)
|
|
|
|
: BaseType(object, deleter)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
|
|
|
const ObjectType * object(void) const
|
|
|
|
{
|
|
|
|
return static_cast<const ObjectType *>(BaseType::object());
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectType * object(void)
|
|
|
|
{
|
|
|
|
return static_cast<ObjectType *>(BaseType::object());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename TObject, typename TDeleter>
|
2012-05-07 21:21:47 +02:00
|
|
|
class RefCountedObject<TObject, TDeleter, NoType>
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
typedef void BaseType;
|
2012-05-07 21:21:47 +02:00
|
|
|
typedef RefCountedObject<TObject, TDeleter, NoType> ThisType;
|
2012-05-07 15:18:05 +02:00
|
|
|
typedef TObject ObjectType;
|
|
|
|
typedef TDeleter DeleterType;
|
2012-05-07 21:21:47 +02:00
|
|
|
typedef NoType BaseObjectType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
RefCountedObject(ObjectType * object, const DeleterType & deleter)
|
|
|
|
: m_object (object)
|
|
|
|
, m_refCount (0)
|
|
|
|
, m_deleter (deleter)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
GLW_ASSERT(this->m_object != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
~RefCountedObject(void)
|
|
|
|
{
|
|
|
|
this->destroyObject();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool isNull(void) const
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return (this->m_object == 0);
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
void setNull(bool deleteObject)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
if (deleteObject)
|
|
|
|
{
|
|
|
|
this->destroyObject();
|
|
|
|
}
|
|
|
|
this->m_object = 0;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const ObjectType * object(void) const
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->m_object;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectType * object(void)
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->m_object;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
const DeleterType & deleter(void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->m_deleter;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
DeleterType & deleter(void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->m_deleter;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ref(void)
|
|
|
|
{
|
|
|
|
this->m_refCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void unref(void)
|
|
|
|
{
|
|
|
|
GLW_ASSERT(this->m_refCount > 0);
|
|
|
|
this->m_refCount--;
|
|
|
|
if (this->m_refCount == 0)
|
|
|
|
{
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
int refCount(void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->m_refCount;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectType * m_object;
|
|
|
|
int m_refCount;
|
|
|
|
DeleterType m_deleter;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
RefCountedObject(const ThisType & other);
|
2012-04-30 20:23:53 +02:00
|
|
|
ThisType & operator = (const ThisType & other);
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
void destroyObject(void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
if (this->m_object == 0) return;
|
|
|
|
this->m_deleter(this->m_object);
|
|
|
|
this->m_object = 0;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T> struct RefCountedObjectTraits { typedef RefCountedObject<T, typename DeleterOf<T>::Type, typename BaseOf<T>::Type> Type; };
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename TObject, typename TDeleter, typename TBaseObject>
|
|
|
|
class ObjectSharedPointer : public ObjectSharedPointer<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type>
|
|
|
|
{
|
2012-04-30 20:23:53 +02:00
|
|
|
public:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
typedef ObjectSharedPointer<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type> BaseType;
|
|
|
|
typedef ObjectSharedPointer<TObject, TDeleter, TBaseObject> ThisType;
|
|
|
|
typedef TObject ObjectType;
|
|
|
|
typedef TDeleter DeleterType;
|
|
|
|
typedef TBaseObject BaseObjectType;
|
|
|
|
typedef RefCountedObject<ObjectType, DeleterType, BaseObjectType> RefCountedObjectType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectSharedPointer(void)
|
|
|
|
: BaseType()
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectSharedPointer(const ThisType & other)
|
|
|
|
: BaseType(other)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectSharedPointer(RefCountedObjectType * refObject)
|
|
|
|
: BaseType(refObject)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
const ObjectType & operator * (void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return (*(this->object()));
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectType & operator * (void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return (*(this->object()));
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
const ObjectType * operator -> (void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->object();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectType * operator -> (void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->object();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
const ObjectType * object(void) const
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return static_cast<const ObjectType *>(BaseType::object());
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectType * object(void)
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return static_cast<ObjectType *>(BaseType::object());
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
RefCountedObjectType * refObject(void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return static_cast<RefCountedObjectType *>(BaseType::refObject());
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename TObject, typename TDeleter>
|
2012-05-07 21:21:47 +02:00
|
|
|
class ObjectSharedPointer<TObject, TDeleter, NoType>
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
typedef void BaseType;
|
2012-05-07 21:21:47 +02:00
|
|
|
typedef ObjectSharedPointer<TObject, TDeleter, NoType> ThisType;
|
2012-05-07 15:18:05 +02:00
|
|
|
typedef TObject ObjectType;
|
|
|
|
typedef TDeleter DeleterType;
|
2012-05-07 21:21:47 +02:00
|
|
|
typedef NoType BaseObjectType;
|
|
|
|
typedef RefCountedObject<ObjectType, DeleterType, NoType> RefCountedObjectType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectSharedPointer(void)
|
|
|
|
: m_refObject(0)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectSharedPointer(const ThisType & other)
|
|
|
|
: m_refObject(0)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
this->attach(other.refObject());
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectSharedPointer(RefCountedObjectType * refObject)
|
|
|
|
: m_refObject(0)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
this->attach(refObject);
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
~ObjectSharedPointer(void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
this->detach();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
bool isNull(void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
if (this->m_refObject == 0) return true;
|
|
|
|
return this->m_refObject->isNull();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
void setNull(void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
this->detach();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
const ObjectType & operator * (void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return (*(this->object()));
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectType & operator * (void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return (*(this->object()));
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
const ObjectType * operator -> (void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->object();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectType * operator -> (void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->object();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
operator bool (void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return (!this->isNull());
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ThisType & operator = (const ThisType & other)
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
this->attach(other.refObject());
|
2012-04-30 20:23:53 +02:00
|
|
|
return (*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
const ObjectType * object(void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
GLW_ASSERT(!this->isNull());
|
|
|
|
return this->m_refObject->object();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
ObjectType * object(void)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
GLW_ASSERT(!this->isNull());
|
|
|
|
return this->m_refObject->object();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
RefCountedObjectType * refObject(void) const
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
return this->m_refObject;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
RefCountedObjectType * m_refObject;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
void attach(RefCountedObjectType * reObject)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
|
|
|
this->detach();
|
2012-05-07 15:18:05 +02:00
|
|
|
this->m_refObject = reObject;
|
|
|
|
if (this->m_refObject != 0)
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
this->m_refObject->ref();
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void detach(void)
|
|
|
|
{
|
2012-05-07 15:18:05 +02:00
|
|
|
if (this->m_refObject == 0) return;
|
|
|
|
this->m_refObject->unref();
|
|
|
|
this->m_refObject = 0;
|
2012-04-30 20:23:53 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
template <typename T> struct ObjectSharedPointerTraits { typedef ObjectSharedPointer<T, typename DeleterOf<typename RootOf<T>::Type>::Type, typename BaseOf<T>::Type> Type; };
|
|
|
|
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // GLW_BOOKKEEPING_H
|