#ifndef GLW_BOOKKEEPING_H #define GLW_BOOKKEEPING_H #include "./common.h" namespace glw { class Context; namespace detail { template class SharedObjectBase { friend class Context; public: typedef void BaseType; typedef SharedObjectBase ThisType; typedef TObject ObjectType; bool isNull(void) const { return (this->m_object == 0); } void setNull(void) { this->m_object = 0; } const ObjectType * object(void) const { return this->m_object; } ObjectType * object(void) { return this->m_object; } void ref(void) { this->m_refCount++; } void unref(void) { GLW_ASSERT(this->m_refCount > 0); this->m_refCount--; if (this->m_refCount == 0) { if (this->m_object != 0) { this->signalDestruction(); } delete this; } } protected: Context * m_context; ObjectType * m_object; int m_refCount; SharedObjectBase(Context * Context, ObjectType * Object) : m_context (Context) , m_object (Object) , m_refCount (0) { GLW_ASSERT(this->m_context != 0); GLW_ASSERT(this->m_object != 0); } private: SharedObjectBase(const ThisType & other); ThisType & operator = (const ThisType & other); inline void signalDestruction(void); }; template class SharedObject; template class SharedObjectTraits { public: typedef void BaseType; typedef SharedObjectTraits ThisType; typedef TObject ObjectType; typedef TObjectBase ObjectBaseType; typedef SharedObject SharedObjectBaseType; }; template class SharedObjectTraits { public: typedef void BaseType; typedef SharedObjectTraits ThisType; typedef TObject ObjectType; typedef void ObjectBaseType; typedef SharedObjectBase SharedObjectBaseType; }; template class SharedObject : public SharedObjectTraits::SharedObjectBaseType { friend class Context; public: typedef typename SharedObjectTraits::SharedObjectBaseType BaseType; typedef SharedObject ThisType; typedef TObject ObjectType; const ObjectType * object(void) const { return static_cast(BaseType::object()); } ObjectType * object(void) { return static_cast(BaseType::object()); } protected: SharedObject(Context * Context, ObjectType * Object) : BaseType(Context, Object) { ; } private: SharedObject(const ThisType & other); ThisType & operator = (const ThisType & other); }; template class SharedObjectBinding { friend class Context; public: typedef void BaseType; typedef SharedObjectBinding ThisType; typedef TObject ObjectType; typedef ObjectType UnsafeType; ~SharedObjectBinding(void) { this->detach(); } bool isNull(void) const { if (this->m_shared == 0) return true; return this->m_shared->isNull(); } void setNull(void) { this->m_shared = 0; } const ObjectType * object(void) const { GLW_ASSERT(!this->isNull()); const ObjectType * obj = this->m_shared->object(); obj->setBinding(this->m_target, this->m_unit); return obj; } ObjectType * object(void) { GLW_ASSERT(!this->isNull()); ObjectType * obj = this->m_shared->object(); obj->setBinding(this->m_target, this->m_unit); return obj; } GLenum target(void) const { return this->m_target; } GLint unit(void) const { return this->m_unit; } 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; } } protected: typedef SharedObject SharedObjectType; SharedObjectBinding(SharedObjectType * shared, GLenum target, GLint unit) : m_shared (0) , m_refCount (0) , m_target (target) , m_unit (unit) { this->attach(shared); } private: SharedObjectType * m_shared; int m_refCount; GLenum m_target; GLint m_unit; SharedObjectBinding(const ThisType & other); ThisType & operator = (const ThisType & other); void attach(SharedObjectType * shared) { this->detach(); this->m_shared = shared; if (this->m_shared != 0) { this->m_shared->ref(); } } void detach(void) { if (this->m_shared == 0) return; this->m_shared->unref(); this->m_shared = 0; } }; template class SafeHandleBase { friend class Context; public: typedef void BaseType; typedef SafeHandleBase ThisType; typedef TObject ObjectType; typedef typename ObjectType::SafeType SafeType; SafeHandleBase(void) : m_shared(0) { ; } SafeHandleBase(const ThisType & other) : m_shared(0) { this->attach(other.shared()); } ~SafeHandleBase(void) { this->detach(); } bool isNull(void) const { if (this->m_shared == 0) return true; return this->m_shared->isNull(); } void setNull(void) { this->detach(); } const SafeType * operator -> (void) const { GLW_ASSERT(!this->isNull()); return this->m_shared->object(); } SafeType * operator -> (void) { GLW_ASSERT(!this->isNull()); return this->m_shared->object(); } ThisType & operator = (const ThisType & other) { this->attach(other.shared()); return (*this); } protected: typedef SharedObject SharedObjectType; SafeHandleBase(SharedObjectType * shared) : m_shared(0) { this->attach(shared); } const ObjectType * object(void) const { if (this->m_shared == 0) return 0; return this->m_shared->object(); } ObjectType * object(void) { if (this->m_shared == 0) return 0; return this->m_shared->object(); } SharedObjectType * shared(void) const { return this->m_shared; } private: SharedObjectType * m_shared; void attach(SharedObjectType * shared) { this->detach(); this->m_shared = shared; if (this->m_shared != 0) { this->m_shared->ref(); } } void detach(void) { if (this->m_shared == 0) return; this->m_shared->unref(); this->m_shared = 0; } }; template class SafeHandle; template class SafeHandleTraits { public: typedef void BaseType; typedef SafeHandleTraits ThisType; typedef TObject ObjectType; typedef TObjectBase ObjectBaseType; typedef SafeHandle SafeHandleBaseType; }; template class SafeHandleTraits { public: typedef void BaseType; typedef SafeHandleTraits ThisType; typedef TObject ObjectType; typedef void ObjectBaseType; typedef SafeHandleBase SafeHandleBaseType; }; template class SafeHandle : public SafeHandleTraits::SafeHandleBaseType { friend class Context; public: typedef typename SafeHandleTraits::SafeHandleBaseType BaseType; typedef SafeHandle ThisType; typedef TObject ObjectType; typedef typename ObjectType::SafeType SafeType; SafeHandle(void) : BaseType() { ; } SafeHandle(const ThisType & other) : BaseType(other) { ; } const SafeType * operator -> (void) const { return dynamic_cast(BaseType:: operator ->()); } SafeType * operator -> (void) { return dynamic_cast(BaseType:: operator ->()); } /* ThisType & operator = (const ThisType & other) { this->attach(other.shared()); return (*this); } */ operator bool (void) const { return !this->isNull(); } protected: typedef SharedObject SharedObjectType; SafeHandle(SharedObjectType * shared) : BaseType(shared) { ; } const ObjectType * object(void) const { return static_cast(BaseType::object()); } ObjectType * object(void) { return static_cast(BaseType::object()); } SharedObjectType * shared(void) const { return static_cast(BaseType::shared()); } }; template class UnsafeHandle { friend class Context; public: typedef void BaseType; typedef UnsafeHandle ThisType; typedef TObject ObjectType; typedef ObjectType UnsafeType; UnsafeHandle(void) : m_shared(0) { ; } UnsafeHandle(const ThisType & other) : m_shared(0) { this->attach(other.shared()); } ~UnsafeHandle(void) { this->detach(); } bool isNull(void) const { if (this->m_shared == 0) return true; return this->m_shared->isNull(); } void setNull(void) { this->detach(); } const UnsafeType * operator -> (void) const { GLW_ASSERT(!this->isNull()); return this->m_shared->object(); } UnsafeType * operator -> (void) { GLW_ASSERT(!this->isNull()); return this->m_shared->object(); } ThisType & operator = (const ThisType & other) { this->attach(other.shared()); return (*this); } operator bool (void) const { return !this->isNull(); } protected: typedef SharedObjectBinding SharedObjectBindingType; UnsafeHandle(SharedObjectBindingType * shared) : m_shared(0) { this->attach(shared); } const ObjectType * Object(void) const { if (this->m_shared == 0) return true; return this->m_shared->object(); } ObjectType * Object(void) { if (this->m_shared == 0) return true; return this->m_shared->object(); } private: SharedObjectBindingType * m_shared; void attach(SharedObjectBindingType * shared) { this->detach(); this->m_shared = shared; if (this->m_shared != 0) { this->m_shared->ref(); } } void detach(void) { if (this->m_shared == 0) return; this->m_shared->unref(); this->m_shared = 0; } SharedObjectBindingType * shared(void) const { return this->m_shared; } }; }; }; #endif // GLW_BOOKKEEPING_H