#pragma once #include "spinlock.h" #include <cassert> namespace vlc { template<typename TargetClass, bool threadSafe = true> class Refcounted { using RefcountType = uint32_t; volatile RefcountType m_refCount = 0; Spinlock m_lock; public: RefcountType incRef() { m_lock.lock(); auto result = m_refCount; m_refCount++; m_lock.unlock(); return result; } RefcountType decRef() { m_lock.lock(); assert(m_refCount > 0); auto result = m_refCount; m_refCount--; m_lock.unlock(); return result; } RefcountType refs() const { return m_refCount; } protected: Refcounted() = default; ~Refcounted() = default; explicit Refcounted(RefcountType initial_refs) : m_refCount(initial_refs) { } }; template<typename TargetClass> class Refcounted<TargetClass, false> { using RefcountType = uint32_t; RefcountType m_refCount = 0; public: RefcountType incRef() { auto result = m_refCount; m_refCount++; return result; } RefcountType decRef() { assert(m_refCount > 0); auto result = m_refCount; m_refCount--; return result; } RefcountType refs() const { return m_refCount; } protected: Refcounted() = default; ~Refcounted() = default; explicit Refcounted(RefcountType initial_refs) : m_refCount(initial_refs) { } }; } template<typename T> void intrusiveIncRef(vlc::Refcounted<T>* ptr) { if (ptr) { ptr->incRef(); } } template<typename T> void intrusiveDecRef(vlc::Refcounted<T>* ptr) { if (ptr && ptr->decRef() == 1) { delete static_cast<T*>(ptr); } }