From 4fded4cbf3a395af794704c236467904b111fa74 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 30 May 2024 10:23:22 +0200 Subject: [PATCH] windows-once: Free allocated resources when done. Based on an observation regarding Cygwin's pthread_once implementation by Takashi Yano at and * lib/windows-once.h (glwthread_once_t): Add field 'num_threads'. (GLWTHREAD_ONCE_INIT): Initialize it to zero. * lib/windows-once.c (glwthread_once): Increment num_threads while the thread uses the lock. Let the last thread that uses the lock destroy it. --- ChangeLog | 12 ++++++++++++ lib/windows-once.c | 7 +++++++ lib/windows-once.h | 3 ++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7b376ed76b..1823d53b73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2024-05-30 Bruno Haible + + windows-once: Free allocated resources when done. + Based on an observation regarding Cygwin's pthread_once implementation + by Takashi Yano at + and + + * lib/windows-once.h (glwthread_once_t): Add field 'num_threads'. + (GLWTHREAD_ONCE_INIT): Initialize it to zero. + * lib/windows-once.c (glwthread_once): Increment num_threads while the + thread uses the lock. Let the last thread that uses the lock destroy it. + 2024-05-29 Bruno Haible call_once tests: Fix link error on mingw. diff --git a/lib/windows-once.c b/lib/windows-once.c index 17854f5c09..b6e1c77566 100644 --- a/lib/windows-once.c +++ b/lib/windows-once.c @@ -29,6 +29,7 @@ glwthread_once (glwthread_once_t *once_control, void (*initfunction) (void)) { if (once_control->inited <= 0) { + InterlockedIncrement (&once_control->num_threads); if (InterlockedIncrement (&once_control->started) == 0) { /* This thread is the first one to come to this once_control. */ @@ -58,5 +59,11 @@ glwthread_once (glwthread_once_t *once_control, void (*initfunction) (void)) abort (); } } + /* Here once_control->inited > 0. */ + if (InterlockedDecrement (&once_control->num_threads) == 0) + /* once_control->num_threads is now zero, and once_control->inited is 1. + No other thread will need to use the lock. + We can therefore destroy the lock, to free resources. */ + DeleteCriticalSection (&once_control->lock); } } diff --git a/lib/windows-once.h b/lib/windows-once.h index c5bbcd573c..13579b5807 100644 --- a/lib/windows-once.h +++ b/lib/windows-once.h @@ -26,12 +26,13 @@ typedef struct { volatile int inited; + volatile LONG num_threads; volatile LONG started; CRITICAL_SECTION lock; } glwthread_once_t; -#define GLWTHREAD_ONCE_INIT { -1, -1 } +#define GLWTHREAD_ONCE_INIT { -1, 0, -1 } #ifdef __cplusplus extern "C" { -- 2.39.5