1 /** 2 Win32 Implementation for nulib.threading.internal.mutex 3 4 Copyright: 5 Copyright © 2025, Kitsunebi Games 6 Copyright © 2025, Inochi2D Project 7 8 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 9 Authors: Luna Nielsen 10 */ 11 module nulib.win32.threading.mutex; 12 import nulib.threading.internal.mutex; 13 import nulib.win32.common; 14 import numem; 15 16 /** 17 Native implementation of a mutually exclusive lock. 18 */ 19 class Win32Mutex : NativeMutex { 20 private: 21 CRITICAL_SECTION* handle_; 22 23 public: 24 @nogc: 25 26 /// Destructor 27 ~this() nothrow { 28 DeleteCriticalSection(handle_); 29 nu_free(handle_); 30 } 31 32 /** 33 Constructs a mutex. 34 */ 35 this() nothrow { 36 this.handle_ = cast(CRITICAL_SECTION*)nu_malloc(CRITICAL_SECTION.sizeof); 37 38 // Cargo-culting the spin-count in WTF::Lock 39 // See: https://webkit.org/blog/6161/locking-in-webkit/ 40 cast(void)InitializeCriticalSectionAndSpinCount(handle_, 40); 41 } 42 43 /** 44 Increments the internal lock counter. 45 */ 46 override 47 void lock() nothrow @trusted { 48 EnterCriticalSection(handle_); 49 } 50 51 /** 52 Tries to increment the internal lock counter. 53 54 Returns: 55 $(D true) if the mutex was locked, 56 $(D false) otherwise. 57 */ 58 override 59 bool tryLock() nothrow @trusted { 60 return TryEnterCriticalSection(handle_) != 0; 61 } 62 63 /** 64 Decrements the internal lock counter, 65 If the counter reaches 0, the lock is released. 66 */ 67 override 68 void unlock() nothrow @trusted { 69 LeaveCriticalSection(handle_); 70 } 71 } 72 73 extern(C) export 74 NativeMutex _nu_mutex_new() @trusted @nogc nothrow { 75 return nogc_new!Win32Mutex(); 76 } 77 78 // 79 // BINDINGS 80 // 81 extern(Windows) @nogc nothrow: 82 83 /// A critical section object. 84 struct CRITICAL_SECTION { 85 void* DebugInfo; 86 int LockCount; 87 int RecursionCount; 88 void* OwningThread; 89 void* LockSemaphore; 90 size_t SpinCount; 91 } 92 93 extern void DeleteCriticalSection(CRITICAL_SECTION*); 94 extern uint InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION*, uint); 95 extern void EnterCriticalSection(CRITICAL_SECTION*); 96 extern void LeaveCriticalSection(CRITICAL_SECTION*); 97 extern uint TryEnterCriticalSection(CRITICAL_SECTION*);