/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuConditionMutex.NT.hpp Date: 2021-6-12 Author: Reece ***/ #pragma once #include "AuIConditionMutexEx.hpp" #if !defined(_AURUNTIME_GENERICCM) namespace Aurora::Threading::Primitives { // Note: these magic numbers are powers of two such that you can use them as add/sub operations // in place of masking. // ie: add = or // sub = and // assuming the bits are unset/set respectively static auto const kFutexBitWake = 256u; // 2^8 static auto const kFutexBitWait = 512u; // 2^9, next byte over inline HANDLE gKeyedEventHandle { INVALID_HANDLE_VALUE }; // Actually NT5.x struct NT4Mutex { volatile AuUInt32 uWaitCount {}; // yields while bits are high, dec to release one from the semaphore yield }; struct Win32ConditionMutex final { Win32ConditionMutex(); ~Win32ConditionMutex(); bool TryLock(); void Lock(); void Unlock(); AuUInt GetOSHandle(); auline bool TryLockNoSpin(); auline bool TryLockHeavy(); #if !defined(AURORA_FORCE_SRW_LOCKS) NT4Mutex lock_; #else SRWLOCK lock_; #endif }; using ConditionMutexInternal = Win32ConditionMutex; struct ConditionMutexImpl final : IConditionMutexEx { auline bool TryLock() { return mutex.TryLock(); } auline void Lock() { mutex.Unlock(); } auline void Unlock() { mutex.Unlock(); } inline AuUInt GetOSHandle() { return mutex.GetOSHandle(); } ConditionMutexInternal mutex; }; } #endif