win: simplify uv_once implementation
* win: simplify uv_once implementation InitOnceExecuteOnce is available in Windows >= Vista. Ref: https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initonceexecuteonce
This commit is contained in:
parent
6adeeacee7
commit
abc9767034
@ -290,8 +290,8 @@ typedef struct {
|
|||||||
#define UV_ONCE_INIT { 0, NULL }
|
#define UV_ONCE_INIT { 0, NULL }
|
||||||
|
|
||||||
typedef struct uv_once_s {
|
typedef struct uv_once_s {
|
||||||
unsigned char ran;
|
unsigned char unused;
|
||||||
HANDLE event;
|
INIT_ONCE init_once;
|
||||||
} uv_once_t;
|
} uv_once_t;
|
||||||
|
|
||||||
/* Platform-specific definitions for uv_spawn support. */
|
/* Platform-specific definitions for uv_spawn support. */
|
||||||
|
|||||||
@ -32,45 +32,23 @@
|
|||||||
#include "uv.h"
|
#include "uv.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
|
typedef void (*uv__once_cb)(void);
|
||||||
DWORD result;
|
|
||||||
HANDLE existing_event, created_event;
|
|
||||||
|
|
||||||
created_event = CreateEvent(NULL, 1, 0, NULL);
|
typedef struct {
|
||||||
if (created_event == 0) {
|
uv__once_cb callback;
|
||||||
/* Could fail in a low-memory situation? */
|
} uv__once_data_t;
|
||||||
uv_fatal_error(GetLastError(), "CreateEvent");
|
|
||||||
|
static BOOL WINAPI uv__once_inner(INIT_ONCE *once, void* param, void** context) {
|
||||||
|
uv__once_data_t* data = param;
|
||||||
|
|
||||||
|
data->callback();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
existing_event = InterlockedCompareExchangePointer(&guard->event,
|
void uv_once(uv_once_t* guard, uv__once_cb callback) {
|
||||||
created_event,
|
uv__once_data_t data = { .callback = callback };
|
||||||
NULL);
|
InitOnceExecuteOnce(&guard->init_once, uv__once_inner, (void*) &data, NULL);
|
||||||
|
|
||||||
if (existing_event == NULL) {
|
|
||||||
/* We won the race */
|
|
||||||
callback();
|
|
||||||
|
|
||||||
result = SetEvent(created_event);
|
|
||||||
assert(result);
|
|
||||||
guard->ran = 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* We lost the race. Destroy the event we created and wait for the existing
|
|
||||||
* one to become signaled. */
|
|
||||||
CloseHandle(created_event);
|
|
||||||
result = WaitForSingleObject(existing_event, INFINITE);
|
|
||||||
assert(result == WAIT_OBJECT_0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void uv_once(uv_once_t* guard, void (*callback)(void)) {
|
|
||||||
/* Fast case - avoid WaitForSingleObject. */
|
|
||||||
if (guard->ran) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__once_inner(guard, callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user