/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: RWLock.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "RWLock.hpp" namespace Aurora::Threading::Primitives { RWLockImpl::RWLockImpl() : read_(*this), write_(*this) { } RWLockImpl::~RWLockImpl() { mutex_.reset(); condition_.reset(); } bool RWLockImpl::Init() { mutex_ = ConditionMutexUnique(); if (!mutex_) { return false; } condition_ = ConditionVariableUnique(mutex_.get()); if (!condition_) { return false; } return true; } bool RWLockImpl::LockRead(AuUInt64 timeout) { LockGuardPtr lock(mutex_); while (state_ < 0) { if (!condition_->WaitForSignal(timeout)) { return false; } } state_++; return true; } bool RWLockImpl::LockWrite(AuUInt64 timeout) { LockGuardPtr lock(mutex_); while (state_ != 0) { if (!condition_->WaitForSignal(timeout)) { return false; } } state_ = -1; return true; } bool RWLockImpl::TryLockRead() { LockGuardPtr lock(mutex_); if (state_ == -1) { return false; } state_++; return true; } bool RWLockImpl::TryLockWrite() { LockGuardPtr lock(mutex_); if (state_ > 0) { return false; } state_ = -1; return true; } void RWLockImpl::UnlockRead() { LockGuardPtr lock(mutex_); if(--state_ == 0) { condition_->Signal(); } } void RWLockImpl::UnlockWrite() { LockGuardPtr lock(mutex_); state_ = 0; condition_->Broadcast(); } 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(waitable); } }