AuroraRuntime/Source/Threading/Primitives/RWLock.cpp

173 lines
3.0 KiB
C++
Raw Normal View History

2021-06-27 21:25:29 +00:00
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RWLock.cpp
Date: 2021-6-12
Author: Reece
***/
2021-09-30 14:57:41 +00:00
#include <Source/RuntimeInternal.hpp>
2021-06-27 21:25:29 +00:00
#include "RWLock.hpp"
namespace Aurora::Threading::Primitives
{
RWLockImpl::RWLockImpl() : read_(*this), write_(*this)
{
}
RWLockImpl::~RWLockImpl()
{
2021-06-30 09:28:52 +00:00
mutex_.reset();
condition_.reset();
2021-06-27 21:25:29 +00:00
}
bool RWLockImpl::Init()
{
mutex_ = ConditionMutexUnique();
if (!mutex_)
{
return false;
}
condition_ = ConditionVariableUnique(mutex_.get());
if (!condition_)
{
return false;
}
return true;
}
bool RWLockImpl::LockRead(AuUInt64 timeout)
{
2021-09-06 10:58:08 +00:00
AU_LOCK_GUARD(mutex_);
2021-06-30 09:28:52 +00:00
2021-06-27 21:25:29 +00:00
while (state_ < 0)
{
if (!condition_->WaitForSignal(timeout))
{
return false;
}
}
2021-06-27 21:25:29 +00:00
state_++;
2021-06-27 21:25:29 +00:00
return true;
}
bool RWLockImpl::LockWrite(AuUInt64 timeout)
{
2021-09-06 10:58:08 +00:00
AU_LOCK_GUARD(mutex_);
2021-06-27 21:25:29 +00:00
while (state_ != 0)
{
if (!condition_->WaitForSignal(timeout))
{
return false;
}
}
2021-06-27 21:25:29 +00:00
state_ = -1;
2021-06-27 21:25:29 +00:00
return true;
}
bool RWLockImpl::TryLockRead()
{
2021-09-06 10:58:08 +00:00
AU_LOCK_GUARD(mutex_);
2021-06-27 21:25:29 +00:00
if (state_ == -1)
{
return false;
}
state_++;
2021-06-27 21:25:29 +00:00
return true;
}
bool RWLockImpl::TryLockWrite()
{
2021-09-06 10:58:08 +00:00
AU_LOCK_GUARD(mutex_);
2021-06-27 21:25:29 +00:00
if (state_ > 0)
{
return false;
}
state_ = -1;
2021-06-27 21:25:29 +00:00
return true;
}
void RWLockImpl::UnlockRead()
{
2021-09-06 10:58:08 +00:00
AU_LOCK_GUARD(mutex_);
2021-06-27 21:25:29 +00:00
2021-09-06 10:58:08 +00:00
auto val = --state_;
if ((val == 1) && (elevaterPending_))
{
condition_->Signal();
}
if (val == 0)
2021-06-27 21:25:29 +00:00
{
condition_->Signal();
}
2021-06-27 21:25:29 +00:00
}
void RWLockImpl::UnlockWrite()
{
2021-09-06 10:58:08 +00:00
AU_LOCK_GUARD(mutex_);
2021-06-27 21:25:29 +00:00
state_ = 0;
condition_->Broadcast();
}
2021-09-06 10:58:08 +00:00
bool RWLockImpl::UpgradeReadToWrite(AuUInt64 timeout)
{
AU_LOCK_GUARD(mutex_);
while (state_ != 1)
{
elevaterPending_.store(true);
if (!condition_->WaitForSignal(timeout))
{
return false;
}
}
elevaterPending_.store(false);
2021-06-27 21:25:29 +00:00
2021-09-06 10:58:08 +00:00
state_ = -1;
return true;
}
2021-06-27 21:25:29 +00:00
IWaitable *RWLockImpl::AsReadable()
{
return &read_;
}
IWaitable *RWLockImpl::AsWritable()
{
return &write_;
}
AUKN_SYM RWLock *RWLockNew()
{
auto ret = _new RWLockImpl();
if (!ret)
{
return nullptr;
}
if (!ret->Init())
{
delete ret;
return nullptr;
}
return ret;
}
AUKN_SYM void RWLockRelease(RWLock *waitable)
{
SafeDelete<RWLockImpl *>(waitable);
}
}