aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSaúl Ibarra Corretgé <s@saghul.net>2024-03-25 11:57:52 +0100
committerGitHub <noreply@github.com>2024-03-25 11:57:52 +0100
commitabc9767034d7c065e6a861cc398a580d0f94e24f (patch)
tree7648fc2e858991f7574b62977ce11c67ea1dd1ec /src
parent6adeeacee7eb997d60552351b43d65b494745700 (diff)
downloadlibuv-abc9767034d7c065e6a861cc398a580d0f94e24f.tar.gz
libuv-abc9767034d7c065e6a861cc398a580d0f94e24f.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/win/thread.c44
1 files changed, 11 insertions, 33 deletions
diff --git a/src/win/thread.c b/src/win/thread.c
index 57c25e8f..bf39b886 100644
--- a/src/win/thread.c
+++ b/src/win/thread.c
@@ -32,45 +32,23 @@
#include "uv.h"
#include "internal.h"
-static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) {
- DWORD result;
- HANDLE existing_event, created_event;
-
- created_event = CreateEvent(NULL, 1, 0, NULL);
- if (created_event == 0) {
- /* Could fail in a low-memory situation? */
- uv_fatal_error(GetLastError(), "CreateEvent");
- }
+typedef void (*uv__once_cb)(void);
- existing_event = InterlockedCompareExchangePointer(&guard->event,
- created_event,
- NULL);
+typedef struct {
+ uv__once_cb callback;
+} uv__once_data_t;
- if (existing_event == NULL) {
- /* We won the race */
- callback();
+static BOOL WINAPI uv__once_inner(INIT_ONCE *once, void* param, void** context) {
+ uv__once_data_t* data = param;
- result = SetEvent(created_event);
- assert(result);
- guard->ran = 1;
+ data->callback();
- } 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);
- }
+ return TRUE;
}
-
-void uv_once(uv_once_t* guard, void (*callback)(void)) {
- /* Fast case - avoid WaitForSingleObject. */
- if (guard->ran) {
- return;
- }
-
- uv__once_inner(guard, callback);
+void uv_once(uv_once_t* guard, uv__once_cb callback) {
+ uv__once_data_t data = { .callback = callback };
+ InitOnceExecuteOnce(&guard->init_once, uv__once_inner, (void*) &data, NULL);
}