/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuRWLock.hpp Date: 2021-6-12 Author: Reece ***/ #pragma once #include "AuConditionVariable.Generic.hpp" #include "AuConditionMutex.Generic.hpp" #include "ThreadCookie.hpp" namespace Aurora::Threading::Primitives { template struct RWLockImpl; template struct RWLockAccessView : IWaitable { RWLockAccessView(T &impl) : parent_(impl) { } bool Lock(AuUInt64 timeout) override; bool LockNS(AuUInt64 timeout) override; bool TryLock() override; bool HasOSHandle(AuMach &mach) override { return false; } bool HasLockImplementation() override { return true; } void Lock() override { SysAssert(Lock(0)); } void Unlock() override; private: T &parent_; }; template struct RWLockImpl : IRWLock { RWLockImpl(); ~RWLockImpl(); bool LockReadNS(AuUInt64 timeout); bool LockWriteNS(AuUInt64 timeout); bool TryLockRead(); bool TryLockWrite(); void UnlockRead(); void UnlockWrite(); bool UpgradeReadToWrite(AuUInt64 timeout) override; bool DowngradeWriteToRead() override; IWaitable *AsReadable() override; IWaitable *AsWritable() override; bool Init(); private: //bool reentrantWriteLock_ {true}; ThreadCookie_t reentrantWriteLockHandle_ {}; RWLockAccessView read_; RWLockAccessView write_; ConditionMutexImpl mutex_; ConditionVariableImpl condition_; volatile AuInt32 state_ {}; AuInt32 writersPending_ {}; bool bElevaterPending_ {}; }; }