#ifndef GLW_BOOKKEEPING_H #define GLW_BOOKKEEPING_H #include "./common.h" namespace glw { namespace detail { struct NoType { }; template struct DefaultDeleter { void operator () (T * t) { delete t; } }; template struct BaseOf { typedef NoType Type; }; template struct RootOfType { typedef typename RootOfType::Type>::Type Type; }; template struct RootOfType { typedef T Type; }; template struct RootOf { typedef typename RootOfType::Type>::Type Type; }; template struct DeleterOfType { typedef typename DeleterOfType::Type>::Type Type; }; template struct DeleterOfType { typedef DefaultDeleter Type; }; template struct DeleterOf { typedef typename DeleterOfType::Type>::Type Type; }; template class RefCountedObject : public RefCountedObject::Type> { public: typedef RefCountedObject::Type> BaseType; typedef RefCountedObject 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(BaseType::object()); } ObjectType * object(void) { return static_cast(BaseType::object()); } }; template class RefCountedObject { public: typedef void BaseType; typedef RefCountedObject 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 struct RefCountedObjectTraits { typedef RefCountedObject::Type, typename BaseOf::Type> Type; }; template class ObjectSharedPointer : public ObjectSharedPointer::Type> { public: typedef ObjectSharedPointer::Type> BaseType; typedef ObjectSharedPointer ThisType; typedef TObject ObjectType; typedef TDeleter DeleterType; typedef TBaseObject BaseObjectType; typedef RefCountedObject 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(BaseType::object()); } ObjectType * object(void) { return static_cast(BaseType::object()); } RefCountedObjectType * refObject(void) const { return static_cast(BaseType::refObject()); } }; template class ObjectSharedPointer { public: typedef void BaseType; typedef ObjectSharedPointer ThisType; typedef TObject ObjectType; typedef TDeleter DeleterType; typedef NoType BaseObjectType; typedef RefCountedObject 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 struct ObjectSharedPointerTraits { typedef ObjectSharedPointer::Type>::Type, typename BaseOf::Type> Type; }; }; }; #endif // GLW_BOOKKEEPING_H