You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
8.6 KiB
342 lines
8.6 KiB
#ifndef GLW_BOOKKEEPING_H |
|
#define GLW_BOOKKEEPING_H |
|
|
|
#include "./common.h" |
|
|
|
namespace glw |
|
{ |
|
|
|
namespace detail |
|
{ |
|
|
|
struct NoType { }; |
|
template <typename T> struct DefaultDeleter { void operator () (T * t) { delete t; } }; |
|
|
|
template <typename T> struct BaseOf { typedef NoType Type; }; |
|
|
|
template <typename T, typename B> struct RootOfType { typedef typename RootOfType<B, typename BaseOf<B>::Type>::Type Type; }; |
|
template <typename T> struct RootOfType<T, NoType> { typedef T Type; }; |
|
template <typename T> struct RootOf { typedef typename RootOfType<T, typename BaseOf<T>::Type>::Type Type; }; |
|
|
|
template <typename T, typename B> struct DeleterOfType { typedef typename DeleterOfType<B, typename BaseOf<B>::Type>::Type Type; }; |
|
template <typename T> struct DeleterOfType<T, NoType> { typedef DefaultDeleter<T> Type; }; |
|
template <typename T> struct DeleterOf { typedef typename DeleterOfType<T, typename BaseOf<T>::Type>::Type Type; }; |
|
|
|
template <typename TObject, typename TDeleter, typename TBaseObject> |
|
class RefCountedObject : public RefCountedObject<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type> |
|
{ |
|
public: |
|
|
|
typedef RefCountedObject<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type> BaseType; |
|
typedef RefCountedObject<TObject, TDeleter, TBaseObject> ThisType; |
|
typedef TObject ObjectType; |
|
typedef TDeleter DeleterType; |
|
typedef TBaseObject BaseObjectType; |
|
|
|
RefCountedObject(ObjectType * object, const DeleterType & deleter) |
|
: BaseType(object, deleter) |
|
{ |
|
; |
|
} |
|
|
|
const ObjectType * object(void) const |
|
{ |
|
return static_cast<const ObjectType *>(BaseType::object()); |
|
} |
|
|
|
ObjectType * object(void) |
|
{ |
|
return static_cast<ObjectType *>(BaseType::object()); |
|
} |
|
}; |
|
|
|
template <typename TObject, typename TDeleter> |
|
class RefCountedObject<TObject, TDeleter, NoType> |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef RefCountedObject<TObject, TDeleter, NoType> ThisType; |
|
typedef TObject ObjectType; |
|
typedef TDeleter DeleterType; |
|
typedef NoType BaseObjectType; |
|
|
|
RefCountedObject(ObjectType * object, const DeleterType & deleter) |
|
: m_object (object) |
|
, m_refCount (0) |
|
, m_deleter (deleter) |
|
{ |
|
GLW_ASSERT(this->m_object != 0); |
|
} |
|
|
|
~RefCountedObject(void) |
|
{ |
|
this->destroyObject(); |
|
} |
|
|
|
bool isNull(void) const |
|
{ |
|
return (this->m_object == 0); |
|
} |
|
|
|
void setNull(bool deleteObject) |
|
{ |
|
if (deleteObject) |
|
{ |
|
this->destroyObject(); |
|
} |
|
this->m_object = 0; |
|
} |
|
|
|
const ObjectType * object(void) const |
|
{ |
|
return this->m_object; |
|
} |
|
|
|
ObjectType * object(void) |
|
{ |
|
return this->m_object; |
|
} |
|
|
|
const DeleterType & deleter(void) const |
|
{ |
|
return this->m_deleter; |
|
} |
|
|
|
DeleterType & deleter(void) |
|
{ |
|
return this->m_deleter; |
|
} |
|
|
|
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; |
|
} |
|
} |
|
|
|
int refCount(void) const |
|
{ |
|
return this->m_refCount; |
|
} |
|
|
|
private: |
|
|
|
ObjectType * m_object; |
|
int m_refCount; |
|
DeleterType m_deleter; |
|
|
|
RefCountedObject(const ThisType & other); |
|
ThisType & operator = (const ThisType & other); |
|
|
|
void destroyObject(void) |
|
{ |
|
if (this->m_object == 0) return; |
|
this->m_deleter(this->m_object); |
|
this->m_object = 0; |
|
} |
|
}; |
|
|
|
template <typename T> struct RefCountedObjectTraits { typedef RefCountedObject<T, typename DeleterOf<T>::Type, typename BaseOf<T>::Type> Type; }; |
|
|
|
template <typename TObject, typename TDeleter, typename TBaseObject> |
|
class ObjectSharedPointer : public ObjectSharedPointer<TBaseObject, TDeleter, typename BaseOf<TBaseObject>::Type> |
|
{ |
|
public: |
|
|
|
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; |
|
|
|
ObjectSharedPointer(void) |
|
: BaseType() |
|
{ |
|
; |
|
} |
|
|
|
ObjectSharedPointer(const ThisType & other) |
|
: BaseType(other) |
|
{ |
|
; |
|
} |
|
|
|
ObjectSharedPointer(RefCountedObjectType * refObject) |
|
: BaseType(refObject) |
|
{ |
|
; |
|
} |
|
|
|
const ObjectType & operator * (void) const |
|
{ |
|
return (*(this->object())); |
|
} |
|
|
|
ObjectType & operator * (void) |
|
{ |
|
return (*(this->object())); |
|
} |
|
|
|
const ObjectType * operator -> (void) const |
|
{ |
|
return this->object(); |
|
} |
|
|
|
ObjectType * operator -> (void) |
|
{ |
|
return this->object(); |
|
} |
|
|
|
protected: |
|
|
|
const ObjectType * object(void) const |
|
{ |
|
return static_cast<const ObjectType *>(BaseType::object()); |
|
} |
|
|
|
ObjectType * object(void) |
|
{ |
|
return static_cast<ObjectType *>(BaseType::object()); |
|
} |
|
|
|
RefCountedObjectType * refObject(void) const |
|
{ |
|
return static_cast<RefCountedObjectType *>(BaseType::refObject()); |
|
} |
|
}; |
|
|
|
template <typename TObject, typename TDeleter> |
|
class ObjectSharedPointer<TObject, TDeleter, NoType> |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef ObjectSharedPointer<TObject, TDeleter, NoType> ThisType; |
|
typedef TObject ObjectType; |
|
typedef TDeleter DeleterType; |
|
typedef NoType BaseObjectType; |
|
typedef RefCountedObject<ObjectType, DeleterType, NoType> RefCountedObjectType; |
|
|
|
ObjectSharedPointer(void) |
|
: m_refObject(0) |
|
{ |
|
; |
|
} |
|
|
|
ObjectSharedPointer(const ThisType & other) |
|
: m_refObject(0) |
|
{ |
|
this->attach(other.refObject()); |
|
} |
|
|
|
ObjectSharedPointer(RefCountedObjectType * refObject) |
|
: m_refObject(0) |
|
{ |
|
this->attach(refObject); |
|
} |
|
|
|
~ObjectSharedPointer(void) |
|
{ |
|
this->detach(); |
|
} |
|
|
|
bool isNull(void) const |
|
{ |
|
if (this->m_refObject == 0) return true; |
|
return this->m_refObject->isNull(); |
|
} |
|
|
|
void setNull(void) |
|
{ |
|
this->detach(); |
|
} |
|
|
|
const ObjectType & operator * (void) const |
|
{ |
|
return (*(this->object())); |
|
} |
|
|
|
ObjectType & operator * (void) |
|
{ |
|
return (*(this->object())); |
|
} |
|
|
|
const ObjectType * operator -> (void) const |
|
{ |
|
return this->object(); |
|
} |
|
|
|
ObjectType * operator -> (void) |
|
{ |
|
return this->object(); |
|
} |
|
|
|
operator bool (void) const |
|
{ |
|
return (!this->isNull()); |
|
} |
|
|
|
ThisType & operator = (const ThisType & other) |
|
{ |
|
this->attach(other.refObject()); |
|
return (*this); |
|
} |
|
|
|
protected: |
|
|
|
const ObjectType * object(void) const |
|
{ |
|
GLW_ASSERT(!this->isNull()); |
|
return this->m_refObject->object(); |
|
} |
|
|
|
ObjectType * object(void) |
|
{ |
|
GLW_ASSERT(!this->isNull()); |
|
return this->m_refObject->object(); |
|
} |
|
|
|
RefCountedObjectType * refObject(void) const |
|
{ |
|
return this->m_refObject; |
|
} |
|
|
|
private: |
|
|
|
RefCountedObjectType * m_refObject; |
|
|
|
void attach(RefCountedObjectType * reObject) |
|
{ |
|
this->detach(); |
|
this->m_refObject = reObject; |
|
if (this->m_refObject != 0) |
|
{ |
|
this->m_refObject->ref(); |
|
} |
|
} |
|
|
|
void detach(void) |
|
{ |
|
if (this->m_refObject == 0) return; |
|
this->m_refObject->unref(); |
|
this->m_refObject = 0; |
|
} |
|
}; |
|
|
|
template <typename T> struct ObjectSharedPointerTraits { typedef ObjectSharedPointer<T, typename DeleterOf<typename RootOf<T>::Type>::Type, typename BaseOf<T>::Type> Type; }; |
|
|
|
}; |
|
|
|
}; |
|
|
|
#endif // GLW_BOOKKEEPING_H
|
|
|