From 6e44b460203945db1caceb42295f6928eda176ff Mon Sep 17 00:00:00 2001 From: MechSlayer <0jcrespo1996@gmail.com> Date: Fri, 5 Sep 2025 15:24:39 +0200 Subject: [PATCH] feature: implement win32 condition variable synchronization primitive --- .../Source/win32/sync/cond_var.c | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Source/DrangPlatform/Source/win32/sync/cond_var.c diff --git a/Source/DrangPlatform/Source/win32/sync/cond_var.c b/Source/DrangPlatform/Source/win32/sync/cond_var.c new file mode 100644 index 0000000..76f3ad2 --- /dev/null +++ b/Source/DrangPlatform/Source/win32/sync/cond_var.c @@ -0,0 +1,111 @@ +#include +#include + +#include "internal.h" + +size_t drang_cond_size(void) +{ + return sizeof(struct drang_cond); +} + +int drang_cond_new(struct drang_cond **cond) +{ + struct drang_cond *c = NULL; + DRANG_BEGIN_TRY(); + + DRANG_CHECK(cond != NULL, DRANG_EINVAL); + + c = DRANG_TRY_ALLOC_T(struct drang_cond); + + DRANG_TRY(drang_cond_init(c)); + + DRANG_RETURN_IN(cond, c); + + DRANG_CATCH(_) + { + if (c != NULL) { + drang_free(c); + } + } + DRANG_END_TRY(); +} + +void drang_cond_free(struct drang_cond *cond) +{ + if (cond == NULL) { + return; + } + + drang_cond_fini(cond); + drang_free(cond); +} + +int drang_cond_init(struct drang_cond *cond) +{ + DRANG_BEGIN_TRY(); + + DRANG_CHECK(cond != NULL, DRANG_EINVAL); + DRANG_CHECK(!cond->initialized, DRANG_EBUSY); + + InitializeConditionVariable(&cond->cv); + cond->initialized = true; + + DRANG_END_TRY_IGNORE(); +} + +void drang_cond_fini(struct drang_cond *cond) +{ + if (cond == NULL) { + return; + } + + // Windows CONDITION_VARIABLE doesn't require explicit cleanup + cond->initialized = false; +} + +int drang_cond_signal(struct drang_cond *cond) +{ + DRANG_BEGIN_TRY(); + + DRANG_CHECK(cond != NULL, DRANG_EINVAL); + DRANG_CHECK(cond->initialized, DRANG_EINVAL); + + WakeConditionVariable(&cond->cv); + + DRANG_END_TRY_IGNORE(); +} + +int drang_cond_broadcast(struct drang_cond *cond) +{ + DRANG_BEGIN_TRY(); + + DRANG_CHECK(cond != NULL, DRANG_EINVAL); + DRANG_CHECK(cond->initialized, DRANG_EINVAL); + + WakeAllConditionVariable(&cond->cv); + + DRANG_END_TRY_IGNORE(); +} + +int drang_cond_timedwait(struct drang_cond *cond, struct drang_mutex *mutex, uint64_t timeout_ms) +{ + DWORD timeout = (timeout_ms == 0) ? INFINITE : (DWORD)timeout_ms; + BOOL result; + + DRANG_BEGIN_TRY(); + + DRANG_CHECK(cond != NULL, DRANG_EINVAL); + DRANG_CHECK(cond->initialized, DRANG_EINVAL); + DRANG_CHECK(mutex != NULL, DRANG_EINVAL); + DRANG_CHECK(mutex->initialized, DRANG_EINVAL); + + result = SleepConditionVariableCS(&cond->cv, &mutex->cs, timeout); + if (!result) { + if (GetLastError() == ERROR_TIMEOUT) { + DRANG_FAIL(DRANG_ETIMEDOUT); + } + DRANG_FAIL(DRANG_EINVAL); // Generic error for other failures + } + + DRANG_END_TRY_IGNORE(); +} \ No newline at end of file