1 /** 2 Win32 Implementation for nulib.threading.internal.semaphore 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.semaphore; 12 import nulib.threading.internal.semaphore; 13 import nulib.win32.common; 14 import numem; 15 16 /** 17 Native implementation of a semaphore. 18 */ 19 class Win32Semaphore : NativeSemaphore { 20 private: 21 @nogc: 22 HANDLE handle_; 23 24 public: 25 26 /// Destructor 27 ~this() nothrow { 28 auto rc = CloseHandle(handle_); 29 assert(rc, "Failed to destroy semaphore!"); 30 } 31 32 /** 33 Constructs a new Win32 Semaphore. 34 */ 35 this(uint count) nothrow { 36 this.handle_ = CreateSemaphoreA(null, count, int.max, null); 37 assert(handle_, "Failed to create semaphore!"); 38 } 39 40 /** 41 Signals the semaphore. 42 43 Note: 44 Control is not transferred to the waiter. 45 */ 46 override 47 void signal() nothrow @trusted { 48 cast(void)ReleaseSemaphore(handle_, 1, null); 49 } 50 51 /** 52 Suspends the thread until the semaphore is signaled, 53 or the timeout is reached. 54 55 Params: 56 timeout = Timeout in miliseconds to block the 57 calling thread before giving up. 58 59 Returns: 60 $(D true) if the semaphore was signaled in time, 61 $(D false) otherwise. 62 */ 63 override 64 bool await(ulong timeout = 0) nothrow @trusted { 65 if (timeout == 0) { 66 return WaitForSingleObject(handle_, INFINITE) == WAIT_OBJECT_0; 67 } 68 69 long timeLeft = timeout; 70 uint rc; 71 while(timeLeft > 0) { 72 rc = WaitForSingleObject(handle_, timeLeft >= uint.max ? uint.max-1 : cast(uint)timeLeft); 73 if(rc == WAIT_OBJECT_0) 74 return true; 75 76 timeLeft -= uint.max-1; 77 } 78 return false; 79 } 80 81 /** 82 Checks if the semaphore is signalled then 83 awaits on it if is. 84 85 Returns: 86 $(D true) if the semaphore was signalled, 87 $(D false) otherwise. 88 */ 89 override 90 bool tryAwait() nothrow @trusted { 91 return WaitForSingleObject(handle_, 0) == WAIT_OBJECT_0; 92 } 93 } 94 95 extern(C) export 96 NativeSemaphore _nu_semaphore_new(uint count) @trusted @nogc nothrow { 97 return nogc_new!Win32Semaphore(count); 98 } 99 100 // 101 // BINDINGS 102 // 103 extern(Windows) @nogc nothrow: 104 105 extern HANDLE CreateSemaphoreA(void*, int, int, void*); 106 extern uint ReleaseSemaphore(HANDLE, int, int*);