/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: RWLock.hpp Date: 2021-6-12 Author: Reece ***/ #pragma once namespace Aurora::Threading::Primitives { class RWLockImpl; template class RWLockAccessView : public IWaitable { public: RWLockAccessView(RWLockImpl &impl) : parent_(impl) { } bool Lock(AuUInt64 timeout) override { if constexpr (isread) { return parent_.LockRead(timeout); } else { return parent_.LockWrite(timeout); } } bool TryLock() override { if constexpr (isread) { return parent_.TryLockRead(); } else { return parent_.TryLockWrite(); } } bool HasOSHandle(AuMach &mach) override { return false; } bool HasLockImplementation() override { return true; } void Lock() override { SysAssert(Lock(0)); } void Unlock() override { if constexpr (isread) { parent_.UnlockRead(); } else { parent_.UnlockWrite(); } } private: RWLockImpl &parent_; }; class RWLockImpl : public RWLock { public: RWLockImpl(); ~RWLockImpl(); bool LockRead(AuUInt64 timeout); bool LockWrite(AuUInt64 timeout); bool TryLockRead(); bool TryLockWrite(); void UnlockRead(); void UnlockWrite(); IWaitable *AsReadable() override; IWaitable *AsWritable() override; bool Init(); private: RWLockAccessView read_; RWLockAccessView write_; ConditionMutexUnique_t mutex_; ConditionVariableUnique_t condition_; std::atomic state_; }; }