diff options
author | Clint Adams <clint@debian.org> | 2021-08-31 08:53:27 -0400 |
---|---|---|
committer | Clint Adams <clint@debian.org> | 2021-08-31 08:53:27 -0400 |
commit | f24d9c72cbde1abddef18e427b818e5b6266a5e0 (patch) | |
tree | f10e939c9cb7b767cb51dce4a84ec9872f3c61b1 /lib/windows-once.c | |
parent | c7cd1604feb9bce8b62e9a5a306b8eeb30a11c97 (diff) | |
parent | c50de48f2ed0b9476c3389fd07a85a5e8be798e2 (diff) |
Update upstream source from tag 'upstream/v4.8'
Update to upstream version '4.8'
with Debian dir 33bfe3afa4d1f33d660b71d89a5ac3eba646cc82
Diffstat (limited to 'lib/windows-once.c')
-rw-r--r-- | lib/windows-once.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/windows-once.c b/lib/windows-once.c new file mode 100644 index 0000000..c431bd6 --- /dev/null +++ b/lib/windows-once.c @@ -0,0 +1,62 @@ +/* Once-only control (native Windows implementation). + Copyright (C) 2005-2020 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2005. + Based on GCC's gthr-win32.h. */ + +#include <config.h> + +/* Specification. */ +#include "windows-once.h" + +#include <stdlib.h> + +void +glwthread_once (glwthread_once_t *once_control, void (*initfunction) (void)) +{ + if (once_control->inited <= 0) + { + if (InterlockedIncrement (&once_control->started) == 0) + { + /* This thread is the first one to come to this once_control. */ + InitializeCriticalSection (&once_control->lock); + EnterCriticalSection (&once_control->lock); + once_control->inited = 0; + initfunction (); + once_control->inited = 1; + LeaveCriticalSection (&once_control->lock); + } + else + { + /* Don't let once_control->started grow and wrap around. */ + InterlockedDecrement (&once_control->started); + /* Some other thread has already started the initialization. + Yield the CPU while waiting for the other thread to finish + initializing and taking the lock. */ + while (once_control->inited < 0) + Sleep (0); + if (once_control->inited <= 0) + { + /* Take the lock. This blocks until the other thread has + finished calling the initfunction. */ + EnterCriticalSection (&once_control->lock); + LeaveCriticalSection (&once_control->lock); + if (!(once_control->inited > 0)) + abort (); + } + } + } +} |