// This code is in the public domain -- Ignacio Castaņo #ifndef NV_CORE_REFCOUNTED_H #define NV_CORE_REFCOUNTED_H #include "nvcore.h" #include "Debug.h" #define NV_DECLARE_PTR(Class) \ template class SmartPtr; \ typedef SmartPtr Class ## Ptr; \ typedef SmartPtr Class ## ConstPtr namespace nv { /// Weak proxy. class WeakProxy { NV_FORBID_COPY(WeakProxy); public: /// Ctor. WeakProxy(void * ptr) : m_count(0), m_ptr(ptr) { } /// Dtor. ~WeakProxy() { nvCheck( m_count == 0 ); } /// Increase reference count. uint addRef() const { m_count++; return m_count; } /// Decrease reference count and remove when 0. uint release() const { nvCheck( m_count > 0 ); m_count--; if( m_count == 0 ) { delete this; return 0; } return m_count; } /// WeakPtr's call this to determine if their pointer is valid or not. bool isAlive() const { return m_ptr != NULL; } /// Only the actual object should call this. void notifyObjectDied() { m_ptr = NULL; } /// Return proxy pointer. void * ptr() const { return m_ptr; } private: mutable int m_count; void * m_ptr; }; /// Reference counted base class to be used with SmartPtr and WeakPtr. class RefCounted { NV_FORBID_COPY(RefCounted); public: /// Ctor. RefCounted() : m_count(0), m_weak_proxy(NULL) { } /// Virtual dtor. virtual ~RefCounted() { nvCheck( m_count == 0 ); releaseWeakProxy(); } /// Increase reference count. uint addRef() const { m_count++; return m_count; } /// Decrease reference count and remove when 0. uint release() const { nvCheck( m_count > 0 ); m_count--; if( m_count == 0 ) { delete this; return 0; } return m_count; } /// Get weak proxy. WeakProxy * getWeakProxy() const { if (m_weak_proxy == NULL) { m_weak_proxy = new WeakProxy((void *)this); m_weak_proxy->addRef(); } return m_weak_proxy; } /// Release the weak proxy. void releaseWeakProxy() const { if (m_weak_proxy != NULL) { m_weak_proxy->notifyObjectDied(); m_weak_proxy->release(); m_weak_proxy = NULL; } } /// Get reference count. int refCount() const { return m_count; } private: mutable int m_count; mutable WeakProxy * m_weak_proxy; }; } // nv namespace #endif // NV_CORE_REFCOUNTED_H