#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);
|
|
}
|
|
}
|