AuroraRuntime/Include/Aurora/Threading/LockGuard.hpp

86 lines
2.4 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: LockGuard.hpp
Date: 2021-6-10
Author: Reece
***/
#pragma once
namespace Aurora::Threading
{
template <class T>
struct AuOperatorArrow
{
template <class C> static constexpr AuTrueType Test(decltype(&C::operator->));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<const T>(0));
};
template<typename T>
class LockGuard
{
using Constless_t = T;
using ConstlessPtr_t = AuConditional_t<AuIsPointer_v<Constless_t>, Constless_t, Constless_t *>;
using Internal_t = AuRemovePointer_t<Constless_t>;
static const bool kBoolArrowOp = AuOperatorArrow<AuRemovePointer_t<T>>::type::value;
public:
auline LockGuard(const T &lock)
{
ConstlessPtr_t pInterface {};
if constexpr (AuIsPointer_v<T>)
{
pInterface = (ConstlessPtr_t)lock;
}
else
{
pInterface = (ConstlessPtr_t)&lock;
}
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Internal_t>::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Internal_t>::value)
{
pInterface->get()->Lock();
}
else if constexpr (kBoolArrowOp)
{
(*pInterface)->Lock();
}
else
{
pInterface->Lock();
}
this->pAnnoying_ = pInterface;
}
auline ~LockGuard()
{
if (!this->pAnnoying_)
{
return;
}
if constexpr (AuIsBaseOfTemplate<AURORA_RUNTIME_AU_SHARED_PTR, Internal_t>::value || AuIsBaseOfTemplate<AURORA_RUNTIME_AU_UNIQUE_PTR, Internal_t>::value)
{
this->pAnnoying_->get()->Unlock();
}
else if constexpr (kBoolArrowOp)
{
(*this->pAnnoying_)->Unlock();
}
else
{
this->pAnnoying_->Unlock();
}
}
private:
ConstlessPtr_t pAnnoying_ {};
};
#define AU_LOCK_GUARD(variable) Aurora::Threading::LockGuard<decltype(variable)> AU_CONCAT(__stack_lock, __COUNTER__) (variable);
}