feature: implement win32 condition variable synchronization primitive
This commit is contained in:
parent
2cdc7ee455
commit
6e44b46020
1 changed files with 111 additions and 0 deletions
111
Source/DrangPlatform/Source/win32/sync/cond_var.c
Normal file
111
Source/DrangPlatform/Source/win32/sync/cond_var.c
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include <drang/alloc.h>
|
||||||
|
#include <drang/sync.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue