]> Savannah Git Hosting - gnulib.git/commitdiff
windows-once: Free allocated resources when done.
authorBruno Haible <bruno@clisp.org>
Thu, 30 May 2024 08:23:22 +0000 (10:23 +0200)
committerBruno Haible <bruno@clisp.org>
Thu, 30 May 2024 08:23:45 +0000 (10:23 +0200)
Based on an observation regarding Cygwin's pthread_once implementation
by Takashi Yano <takashi.yano@nifty.ne.jp> at
<https://cygwin.com/pipermail/cygwin/2024-January/255182.html> and
<https://cygwin.com/pipermail/cygwin-patches/2024q1/012600.html>

* 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
lib/windows-once.c
lib/windows-once.h

index 7b376ed76bddcb757283b166f9fd2609eeabd20d..1823d53b73b06b09b893573e1265c29602f3ae4a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2024-05-30  Bruno Haible  <bruno@clisp.org>
+
+       windows-once: Free allocated resources when done.
+       Based on an observation regarding Cygwin's pthread_once implementation
+       by Takashi Yano <takashi.yano@nifty.ne.jp> at
+       <https://cygwin.com/pipermail/cygwin/2024-January/255182.html> and
+       <https://cygwin.com/pipermail/cygwin-patches/2024q1/012600.html>
+       * 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  <bruno@clisp.org>
 
        call_once tests: Fix link error on mingw.
index 17854f5c093f7ffb4bb5251683073a9679711210..b6e1c775662021392fbbf2479119e55c444ed21f 100644 (file)
@@ -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);
     }
 }
index c5bbcd573c8068049f18d2af27126ae77c3d336c..13579b580719e988ecbd0bb73aa3e4feb8bbf583 100644 (file)
 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" {