// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
template
class WeakRefTarget;
template
class WeakRefImpl;
//-----------------------------------------------------------------------------
// WeakRef
//-----------------------------------------------------------------------------
template
class WeakRef final
{
friend class WeakRefTarget;
public:
WeakRef(const WeakRef& that):
m_spImpl(that.m_spImpl)
{
}
WeakRef(WeakRef&& that) noexcept:
m_spImpl(std::move(that.m_spImpl))
{
}
const WeakRef& operator=(const WeakRef& that)
{
m_spImpl = that.m_spImpl;
return *this;
}
const WeakRef& operator=(WeakRef&& that) noexcept
{
m_spImpl = std::move(that.m_spImpl);
return *this;
}
SharedPtr GetTarget() const
{
return m_spImpl->GetTarget();
}
private:
explicit WeakRef(const SharedPtr>& spImpl):
m_spImpl(spImpl)
{
}
SharedPtr> m_spImpl;
};
//-----------------------------------------------------------------------------
// WeakRefTarget
//-----------------------------------------------------------------------------
template
class WeakRefTarget: public SharedPtrTarget
{
public:
WeakRefTarget():
m_spWeakRefImpl(new WeakRefImpl(static_cast(this)))
{
}
WeakRef CreateWeakRef() const
{
return WeakRef(m_spWeakRefImpl);
}
protected:
~WeakRefTarget()
{
m_spWeakRefImpl->OnTargetDeleted();
}
private:
SharedPtr> m_spWeakRefImpl;
};
//-----------------------------------------------------------------------------
// WeakRefImpl
//-----------------------------------------------------------------------------
template
class WeakRefImpl final: public SharedPtrTarget
{
friend class WeakRef;
friend class WeakRefTarget;
private:
explicit WeakRefImpl(T* pTarget):
m_pTarget(pTarget)
{
}
SharedPtr GetTarget()
{
SharedPtr spTarget;
BEGIN_MUTEX_SCOPE(m_Mutex)
if (m_pTarget != nullptr)
{
AddRefScope addRefScope(m_pTarget->GetRefCount());
if (addRefScope.GetRefCountValue() > 1)
{
spTarget = m_pTarget;
}
}
END_MUTEX_SCOPE
return spTarget;
}
void OnTargetDeleted()
{
BEGIN_MUTEX_SCOPE(m_Mutex)
m_pTarget = nullptr;
END_MUTEX_SCOPE
}
SimpleMutex m_Mutex;
T* m_pTarget;
};