[PATCH 3/4] pthread: provide `pthread_once()` shims for Windows and for NO_PTHREADS
- From
Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Sep 28, 2026, 15:51 UTC
- Message-ID
- <2f3077b60a7777b8d4c21551f9a8d02034a49cee.1790610691.git.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2240.git.1790610691.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
I am about to introduce logic that needs to perform some initialization once, and once only, even if called concurrently.
This is a perfect job for `pthread_once()`, but Git's source code currently lacks a Win32 shim. So let's add one!
Also provide a trivial shim for `NO_PTHREAD` builds.
Assisted-by: GPT-6 Sol Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> --- compat/win32/pthread.c | 16 ++++++++++++++++ compat/win32/pthread.h | 5 +++++ thread-utils.h | 16 ++++++++++++++++ 3 files changed, 37 insertions(+)
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c index 398caa9602..5af95edd3b 100644 --- a/compat/win32/pthread.c +++ b/compat/win32/pthread.c @@ -60,6 +60,22 @@ pthread_t pthread_self(void) return t; } +static BOOL CALLBACK win32_pthread_once(PINIT_ONCE once UNUSED, + PVOID parameter, + PVOID *context UNUSED) +{ + (*(void (**)(void))parameter)(); + return TRUE; +} + +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) +{ + if (!InitOnceExecuteOnce(once_control, win32_pthread_once, + &init_routine, NULL)) + return err_win_to_posix(GetLastError()); + return 0; +} + int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { if (SleepConditionVariableCS(cond, mutex, INFINITE) == 0) diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h index d80df8d12a..79a6bd9680 100644 --- a/compat/win32/pthread.h +++ b/compat/win32/pthread.h @@ -26,6 +26,11 @@ static inline int return_0(int i UNUSED) { #define pthread_mutex_lock EnterCriticalSection #define pthread_mutex_unlock LeaveCriticalSection +typedef INIT_ONCE pthread_once_t; +#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT + +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); + typedef int pthread_mutexattr_t; #define pthread_mutexattr_init(a) (*(a) = 0) #define pthread_mutexattr_destroy(a) do {} while (0) diff --git a/thread-utils.h b/thread-utils.h index 4961487ed9..98b574eff4 100644 --- a/thread-utils.h +++ b/thread-utils.h @@ -19,6 +19,22 @@ #define pthread_mutex_t int #define pthread_cond_t int #define pthread_key_t int +#define pthread_once_t int +#undef PTHREAD_ONCE_INIT +#define PTHREAD_ONCE_INIT 0 + +static inline int dummy_pthread_once(pthread_once_t *once_control, + void (*init_routine)(void)) +{ + if (!*once_control) { + init_routine(); + *once_control = 1; + } + return 0; +} + +#define pthread_once(once_control, init_routine) \ + dummy_pthread_once((once_control), (init_routine)) #define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex) #define pthread_mutex_lock(mutex)
-- gitgitgadget