diff options
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 00000000..deea5487 --- /dev/null +++ b/lib/windows-once.c @@ -0,0 +1,62 @@ +/* Once-only control (native Windows implementation). +   Copyright (C) 2005-2022 Free Software Foundation, Inc. + +   This file is free software: you can redistribute it and/or modify +   it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. + +   This file 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 Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser 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 (); +            } +        } +    } +}  | 
