Add isnanf module.
[pspp] / lib / lock.h
index 9ca33debcd252ac698c5b4c2a2b977df31b1dfbb..32a35bbc769c52f841077eac1a1a0253535823f3 100644 (file)
@@ -1,20 +1,19 @@
 /* Locking in multithreaded situations.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005-2008 Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU Library General Public License as published
-   by the Free Software Foundation; either version 2, or (at your option)
+   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 2, 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
-   Library General Public License for more details.
+   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 Library General Public
-   License along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-   USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
      Taking the lock:     gl_recursive_lock_lock (name);
      Releasing the lock:  gl_recursive_lock_unlock (name);
      De-initialization:   gl_recursive_lock_destroy (name);
+
+  Once-only execution:
+     Type:                gl_once_t
+     Initializer:         gl_once_define(extern, name)
+     Execution:           gl_once (name, initfunction);
 */
 
 
+#ifndef _LOCK_H
+#define _LOCK_H
+
 /* ========================================================================= */
 
 #if USE_POSIX_THREADS
 # include <pthread.h>
 # include <stdlib.h>
 
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The pthread_in_use() detection needs to be done at runtime.  */
+#  define pthread_in_use() \
+     glthread_in_use ()
+extern int glthread_in_use (void);
+
+# endif
+
 # if USE_POSIX_THREADS_WEAK
 
 /* Use weak references to the POSIX threads library.  */
 #  pragma weak pthread_rwlock_wrlock
 #  pragma weak pthread_rwlock_unlock
 #  pragma weak pthread_rwlock_destroy
+#  pragma weak pthread_once
 #  pragma weak pthread_cond_init
 #  pragma weak pthread_cond_wait
 #  pragma weak pthread_cond_signal
 #   pragma weak pthread_self
 #  endif
 
-#  pragma weak pthread_cancel
-#  define pthread_in_use() (pthread_cancel != NULL)
+#  if !PTHREAD_IN_USE_DETECTION_HARD
+#   pragma weak pthread_cancel
+#   define pthread_in_use() (pthread_cancel != NULL)
+#  endif
 
 # else
 
-#  define pthread_in_use() 1
+#  if !PTHREAD_IN_USE_DETECTION_HARD
+#   define pthread_in_use() 1
+#  endif
 
 # endif
 
@@ -118,15 +143,37 @@ typedef pthread_mutex_t gl_lock_t;
 # define gl_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS pthread_mutex_t NAME;
 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS pthread_mutex_t NAME = PTHREAD_MUTEX_INITIALIZER;
+    STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+    PTHREAD_MUTEX_INITIALIZER
 # define gl_lock_init(NAME) \
-    if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
+    do                                                                  \
+      {                                                                 \
+        if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) \
+          abort ();                                                     \
+      }                                                                 \
+    while (0)
 # define gl_lock_lock(NAME) \
-    if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
+    do                                                            \
+      {                                                           \
+        if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
+          abort ();                                               \
+      }                                                           \
+    while (0)
 # define gl_lock_unlock(NAME) \
-    if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
+    do                                                              \
+      {                                                             \
+        if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
+          abort ();                                                 \
+      }                                                             \
+    while (0)
 # define gl_lock_destroy(NAME) \
-    if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
+    do                                                               \
+      {                                                              \
+        if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
+          abort ();                                                  \
+      }                                                              \
+    while (0)
 
 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 
@@ -138,17 +185,44 @@ typedef pthread_rwlock_t gl_rwlock_t;
 #   define gl_rwlock_define(STORAGECLASS, NAME) \
       STORAGECLASS pthread_rwlock_t NAME;
 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-      STORAGECLASS pthread_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
+      STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
+#   define gl_rwlock_initializer \
+      PTHREAD_RWLOCK_INITIALIZER
 #   define gl_rwlock_init(NAME) \
-      if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
+      do                                                                   \
+        {                                                                  \
+          if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) \
+            abort ();                                                      \
+        }                                                                  \
+      while (0)
 #   define gl_rwlock_rdlock(NAME) \
-      if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
+      do                                                               \
+        {                                                              \
+          if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) \
+            abort ();                                                  \
+        }                                                              \
+      while (0)
 #   define gl_rwlock_wrlock(NAME) \
-      if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
+      do                                                               \
+        {                                                              \
+          if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) \
+            abort ();                                                  \
+        }                                                              \
+      while (0)
 #   define gl_rwlock_unlock(NAME) \
-      if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
+      do                                                               \
+        {                                                              \
+          if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) \
+            abort ();                                                  \
+        }                                                              \
+      while (0)
 #   define gl_rwlock_destroy(NAME) \
-      if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
+      do                                                                \
+        {                                                               \
+          if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) \
+            abort ();                                                   \
+        }                                                               \
+      while (0)
 
 #  else
 
@@ -162,17 +236,44 @@ typedef struct
 #   define gl_rwlock_define(STORAGECLASS, NAME) \
       STORAGECLASS gl_rwlock_t NAME;
 #   define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-      STORAGECLASS gl_rwlock_t NAME = { 0, PTHREAD_MUTEX_INITIALIZER };
+      STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+#   define gl_rwlock_initializer \
+      { 0, PTHREAD_MUTEX_INITIALIZER }
 #   define gl_rwlock_init(NAME) \
-      if (pthread_in_use ()) glthread_rwlock_init (&NAME)
+      do                                  \
+        {                                 \
+          if (pthread_in_use ())          \
+            glthread_rwlock_init (&NAME); \
+        }                                 \
+      while (0)
 #   define gl_rwlock_rdlock(NAME) \
-      if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
+      do                                    \
+        {                                   \
+          if (pthread_in_use ())            \
+            glthread_rwlock_rdlock (&NAME); \
+        }                                   \
+      while (0)
 #   define gl_rwlock_wrlock(NAME) \
-      if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
+      do                                    \
+        {                                   \
+          if (pthread_in_use ())            \
+            glthread_rwlock_wrlock (&NAME); \
+        }                                   \
+      while (0)
 #   define gl_rwlock_unlock(NAME) \
-      if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
+      do                                    \
+        {                                   \
+          if (pthread_in_use ())            \
+            glthread_rwlock_unlock (&NAME); \
+        }                                   \
+      while (0)
 #   define gl_rwlock_destroy(NAME) \
-      if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
+      do                                     \
+        {                                    \
+          if (pthread_in_use ())             \
+            glthread_rwlock_destroy (&NAME); \
+        }                                    \
+      while (0)
 extern void glthread_rwlock_init (gl_rwlock_t *lock);
 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
@@ -195,18 +296,44 @@ typedef struct
 # define gl_rwlock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_rwlock_t NAME;
 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS gl_rwlock_t NAME = \
-      { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 };
+    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+    { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
 # define gl_rwlock_init(NAME) \
-    if (pthread_in_use ()) glthread_rwlock_init (&NAME)
+    do                                  \
+      {                                 \
+        if (pthread_in_use ())          \
+          glthread_rwlock_init (&NAME); \
+      }                                 \
+    while (0)
 # define gl_rwlock_rdlock(NAME) \
-    if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
+    do                                    \
+      {                                   \
+        if (pthread_in_use ())            \
+          glthread_rwlock_rdlock (&NAME); \
+      }                                   \
+    while (0)
 # define gl_rwlock_wrlock(NAME) \
-    if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
+    do                                    \
+      {                                   \
+        if (pthread_in_use ())            \
+          glthread_rwlock_wrlock (&NAME); \
+      }                                   \
+    while (0)
 # define gl_rwlock_unlock(NAME) \
-    if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
+    do                                    \
+      {                                   \
+        if (pthread_in_use ())            \
+          glthread_rwlock_unlock (&NAME); \
+      }                                   \
+    while (0)
 # define gl_rwlock_destroy(NAME) \
-    if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
+    do                                     \
+      {                                    \
+        if (pthread_in_use ())             \
+          glthread_rwlock_destroy (&NAME); \
+      }                                    \
+    while (0)
 extern void glthread_rwlock_init (gl_rwlock_t *lock);
 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
@@ -224,21 +351,44 @@ extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
 typedef pthread_mutex_t gl_recursive_lock_t;
 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
       STORAGECLASS pthread_mutex_t NAME;
+#   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+      STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
 #   ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
-#    define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-       STORAGECLASS pthread_mutex_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+#    define gl_recursive_lock_initializer \
+       PTHREAD_RECURSIVE_MUTEX_INITIALIZER
 #   else
-#    define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-       STORAGECLASS pthread_mutex_t NAME = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+#    define gl_recursive_lock_initializer \
+       PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
 #   endif
 #   define gl_recursive_lock_init(NAME) \
-      if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
+      do                                          \
+        {                                         \
+          if (pthread_in_use ())                  \
+            glthread_recursive_lock_init (&NAME); \
+        }                                         \
+      while (0)
 #   define gl_recursive_lock_lock(NAME) \
-      if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
+      do                                                            \
+        {                                                           \
+          if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) \
+            abort ();                                               \
+        }                                                           \
+      while (0)
 #   define gl_recursive_lock_unlock(NAME) \
-      if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
+      do                                                              \
+        {                                                             \
+          if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) \
+            abort ();                                                 \
+        }                                                             \
+      while (0)
 #   define gl_recursive_lock_destroy(NAME) \
-      if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
+      do                                                               \
+        {                                                              \
+          if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) \
+            abort ();                                                  \
+        }                                                              \
+      while (0)
+extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
 
 #  else
 
@@ -252,16 +402,37 @@ typedef struct
 #   define gl_recursive_lock_define(STORAGECLASS, NAME) \
       STORAGECLASS gl_recursive_lock_t NAME;
 #   define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-      STORAGECLASS gl_recursive_lock_t NAME = \
-        { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 };
+      STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+#   define gl_recursive_lock_initializer \
+      { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
 #   define gl_recursive_lock_init(NAME) \
-      if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
+      do                                          \
+        {                                         \
+          if (pthread_in_use ())                  \
+            glthread_recursive_lock_init (&NAME); \
+        }                                         \
+      while (0)
 #   define gl_recursive_lock_lock(NAME) \
-      if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
+      do                                          \
+        {                                         \
+          if (pthread_in_use ())                  \
+            glthread_recursive_lock_lock (&NAME); \
+        }                                         \
+      while (0)
 #   define gl_recursive_lock_unlock(NAME) \
-      if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
+      do                                            \
+        {                                           \
+          if (pthread_in_use ())                    \
+            glthread_recursive_lock_unlock (&NAME); \
+        }                                           \
+      while (0)
 #   define gl_recursive_lock_destroy(NAME) \
-      if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
+      do                                             \
+        {                                            \
+          if (pthread_in_use ())                     \
+            glthread_recursive_lock_destroy (&NAME); \
+        }                                            \
+      while (0)
 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
@@ -284,16 +455,37 @@ typedef struct
 #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
      STORAGECLASS gl_recursive_lock_t NAME;
 #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-     STORAGECLASS gl_recursive_lock_t NAME = \
-       { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 };
+     STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+#  define gl_recursive_lock_initializer \
+     { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
 #  define gl_recursive_lock_init(NAME) \
-     if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
+     do                                          \
+       {                                         \
+         if (pthread_in_use ())                  \
+           glthread_recursive_lock_init (&NAME); \
+       }                                         \
+     while (0)
 #  define gl_recursive_lock_lock(NAME) \
-     if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
+     do                                          \
+       {                                         \
+         if (pthread_in_use ())                  \
+           glthread_recursive_lock_lock (&NAME); \
+       }                                         \
+     while (0)
 #  define gl_recursive_lock_unlock(NAME) \
-     if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
+     do                                            \
+       {                                           \
+         if (pthread_in_use ())                    \
+           glthread_recursive_lock_unlock (&NAME); \
+       }                                           \
+     while (0)
 #  define gl_recursive_lock_destroy(NAME) \
-     if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
+     do                                             \
+       {                                            \
+         if (pthread_in_use ())                     \
+           glthread_recursive_lock_destroy (&NAME); \
+       }                                            \
+     while (0)
 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
@@ -301,6 +493,32 @@ extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 
 # endif
 
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef pthread_once_t gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+    STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
+# define gl_once(NAME, INITFUNCTION) \
+    do                                                   \
+      {                                                  \
+        if (pthread_in_use ())                           \
+          {                                              \
+            if (pthread_once (&NAME, INITFUNCTION) != 0) \
+              abort ();                                  \
+          }                                              \
+        else                                             \
+          {                                              \
+            if (glthread_once_singlethreaded (&NAME))    \
+              INITFUNCTION ();                           \
+          }                                              \
+      }                                                  \
+    while (0)
+extern int glthread_once_singlethreaded (pthread_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
 /* ========================================================================= */
@@ -312,6 +530,10 @@ extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 # include <pth.h>
 # include <stdlib.h>
 
+# ifdef __cplusplus
+extern "C" {
+# endif
+
 # if USE_PTH_THREADS_WEAK
 
 /* Use weak references to the GNU Pth threads library.  */
@@ -322,6 +544,7 @@ extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 #  pragma weak pth_rwlock_init
 #  pragma weak pth_rwlock_acquire
 #  pragma weak pth_rwlock_release
+#  pragma weak pth_once
 
 #  pragma weak pth_cancel
 #  define pth_in_use() (pth_cancel != NULL)
@@ -338,13 +561,30 @@ typedef pth_mutex_t gl_lock_t;
 # define gl_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS pth_mutex_t NAME;
 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
+    STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+    PTH_MUTEX_INIT
 # define gl_lock_init(NAME) \
-    if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
+    do                                               \
+      {                                              \
+        if (pth_in_use() && !pth_mutex_init (&NAME)) \
+          abort ();                                  \
+      }                                              \
+    while (0)
 # define gl_lock_lock(NAME) \
-    if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+    do                                                           \
+      {                                                          \
+        if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
+          abort ();                                              \
+      }                                                          \
+    while (0)
 # define gl_lock_unlock(NAME) \
-    if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
+    do                                                  \
+      {                                                 \
+        if (pth_in_use() && !pth_mutex_release (&NAME)) \
+          abort ();                                     \
+      }                                                 \
+    while (0)
 # define gl_lock_destroy(NAME) \
     (void)(&NAME)
 
@@ -354,15 +594,39 @@ typedef pth_rwlock_t gl_rwlock_t;
 #  define gl_rwlock_define(STORAGECLASS, NAME) \
      STORAGECLASS pth_rwlock_t NAME;
 #  define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-     STORAGECLASS pth_rwlock_t NAME = PTH_RWLOCK_INIT;
+     STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
+#  define gl_rwlock_initializer \
+     PTH_RWLOCK_INIT
 #  define gl_rwlock_init(NAME) \
-     if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
+     do                                                \
+       {                                               \
+         if (pth_in_use() && !pth_rwlock_init (&NAME)) \
+           abort ();                                   \
+       }                                               \
+     while (0)
 #  define gl_rwlock_rdlock(NAME) \
-     if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
+     do                                                              \
+       {                                                             \
+         if (pth_in_use()                                            \
+             && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) \
+           abort ();                                                 \
+       }                                                             \
+     while (0)
 #  define gl_rwlock_wrlock(NAME) \
-     if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
+     do                                                              \
+       {                                                             \
+         if (pth_in_use()                                            \
+             && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) \
+           abort ();                                                 \
+       }                                                             \
+     while (0)
 #  define gl_rwlock_unlock(NAME) \
-     if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
+     do                                                   \
+       {                                                  \
+         if (pth_in_use() && !pth_rwlock_release (&NAME)) \
+           abort ();                                      \
+       }                                                  \
+     while (0)
 #  define gl_rwlock_destroy(NAME) \
      (void)(&NAME)
 
@@ -373,16 +637,61 @@ typedef pth_mutex_t gl_recursive_lock_t;
 #  define gl_recursive_lock_define(STORAGECLASS, NAME) \
      STORAGECLASS pth_mutex_t NAME;
 #  define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-     STORAGECLASS pth_mutex_t NAME = PTH_MUTEX_INIT;
+     STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
+#  define gl_recursive_lock_initializer \
+     PTH_MUTEX_INIT
 #  define gl_recursive_lock_init(NAME) \
-     if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
+     do                                               \
+       {                                              \
+         if (pth_in_use() && !pth_mutex_init (&NAME)) \
+           abort ();                                  \
+       }                                              \
+     while (0)
 #  define gl_recursive_lock_lock(NAME) \
-     if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
+     do                                                           \
+       {                                                          \
+         if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) \
+           abort ();                                              \
+       }                                                          \
+     while (0)
 #  define gl_recursive_lock_unlock(NAME) \
-     if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
+     do                                                  \
+       {                                                 \
+         if (pth_in_use() && !pth_mutex_release (&NAME)) \
+           abort ();                                     \
+       }                                                 \
+     while (0)
 #  define gl_recursive_lock_destroy(NAME) \
      (void)(&NAME)
 
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef pth_once_t gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+    STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
+# define gl_once(NAME, INITFUNCTION) \
+    do                                                                \
+      {                                                               \
+        if (pth_in_use ())                                            \
+          {                                                           \
+            void (*gl_once_temp) (void) = INITFUNCTION;               \
+            if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
+              abort ();                                               \
+          }                                                           \
+        else                                                          \
+          {                                                           \
+            if (glthread_once_singlethreaded (&NAME))                 \
+              INITFUNCTION ();                                        \
+          }                                                           \
+      }                                                               \
+    while (0)
+extern void glthread_once_call (void *arg);
+extern int glthread_once_singlethreaded (pth_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
 /* ========================================================================= */
@@ -395,6 +704,10 @@ typedef pth_mutex_t gl_recursive_lock_t;
 # include <synch.h>
 # include <stdlib.h>
 
+# ifdef __cplusplus
+extern "C" {
+# endif
+
 # if USE_SOLARIS_THREADS_WEAK
 
 /* Use weak references to the old Solaris threads library.  */
@@ -425,15 +738,37 @@ typedef mutex_t gl_lock_t;
 # define gl_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS mutex_t NAME;
 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS mutex_t NAME = DEFAULTMUTEX;
+    STORAGECLASS mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+    DEFAULTMUTEX
 # define gl_lock_init(NAME) \
-    if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
+    do                                                                       \
+      {                                                                      \
+        if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) \
+          abort ();                                                          \
+      }                                                                      \
+    while (0)
 # define gl_lock_lock(NAME) \
-    if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
+    do                                                   \
+      {                                                  \
+        if (thread_in_use () && mutex_lock (&NAME) != 0) \
+          abort ();                                      \
+      }                                                  \
+    while (0)
 # define gl_lock_unlock(NAME) \
-    if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
+    do                                                     \
+      {                                                    \
+        if (thread_in_use () && mutex_unlock (&NAME) != 0) \
+          abort ();                                        \
+      }                                                    \
+    while (0)
 # define gl_lock_destroy(NAME) \
-    if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
+    do                                                      \
+      {                                                     \
+        if (thread_in_use () && mutex_destroy (&NAME) != 0) \
+          abort ();                                         \
+      }                                                     \
+    while (0)
 
 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 
@@ -441,17 +776,44 @@ typedef rwlock_t gl_rwlock_t;
 # define gl_rwlock_define(STORAGECLASS, NAME) \
     STORAGECLASS rwlock_t NAME;
 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS rwlock_t NAME = DEFAULTRWLOCK;
+    STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+    DEFAULTRWLOCK
 # define gl_rwlock_init(NAME) \
-    if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
+    do                                                                        \
+      {                                                                       \
+        if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) \
+          abort ();                                                           \
+      }                                                                       \
+    while (0)
 # define gl_rwlock_rdlock(NAME) \
-    if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
+    do                                                  \
+      {                                                 \
+        if (thread_in_use () && rw_rdlock (&NAME) != 0) \
+          abort ();                                     \
+      }                                                 \
+    while (0)
 # define gl_rwlock_wrlock(NAME) \
-    if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
+    do                                                  \
+      {                                                 \
+        if (thread_in_use () && rw_wrlock (&NAME) != 0) \
+          abort ();                                     \
+      }                                                 \
+    while (0)
 # define gl_rwlock_unlock(NAME) \
-    if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
+    do                                                  \
+      {                                                 \
+        if (thread_in_use () && rw_unlock (&NAME) != 0) \
+          abort ();                                     \
+      }                                                 \
+    while (0)
 # define gl_rwlock_destroy(NAME) \
-    if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
+    do                                                       \
+      {                                                      \
+        if (thread_in_use () && rwlock_destroy (&NAME) != 0) \
+          abort ();                                          \
+      }                                                      \
+    while (0)
 
 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 
@@ -468,20 +830,73 @@ typedef struct
 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_recursive_lock_t NAME;
 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS gl_recursive_lock_t NAME = { DEFAULTMUTEX, (thread_t) 0, 0 };
+    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+    { DEFAULTMUTEX, (thread_t) 0, 0 }
 # define gl_recursive_lock_init(NAME) \
-    if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
+    do                                          \
+      {                                         \
+        if (thread_in_use ())                   \
+          glthread_recursive_lock_init (&NAME); \
+      }                                         \
+    while (0)
 # define gl_recursive_lock_lock(NAME) \
-    if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
+    do                                          \
+      {                                         \
+        if (thread_in_use ())                   \
+          glthread_recursive_lock_lock (&NAME); \
+      }                                         \
+    while (0)
 # define gl_recursive_lock_unlock(NAME) \
-    if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
+    do                                            \
+      {                                           \
+        if (thread_in_use ())                     \
+          glthread_recursive_lock_unlock (&NAME); \
+      }                                           \
+    while (0)
 # define gl_recursive_lock_destroy(NAME) \
-    if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
+    do                                             \
+      {                                            \
+        if (thread_in_use ())                      \
+          glthread_recursive_lock_destroy (&NAME); \
+      }                                            \
+    while (0)
 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef struct
+        {
+          volatile int inited;
+          mutex_t mutex;
+        }
+        gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+    STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
+# define gl_once(NAME, INITFUNCTION) \
+    do                                                \
+      {                                               \
+        if (thread_in_use ())                         \
+          {                                           \
+            glthread_once (&NAME, INITFUNCTION);      \
+          }                                           \
+        else                                          \
+          {                                           \
+            if (glthread_once_singlethreaded (&NAME)) \
+              INITFUNCTION ();                        \
+          }                                           \
+      }                                               \
+    while (0)
+extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
+extern int glthread_once_singlethreaded (gl_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
 /* ========================================================================= */
@@ -490,6 +905,10 @@ extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 
 # include <windows.h>
 
+# ifdef __cplusplus
+extern "C" {
+# endif
+
 /* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
    Semaphore types, because
      - we need only to synchronize inside a single process (address space),
@@ -514,7 +933,9 @@ typedef struct
 # define gl_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_lock_t NAME;
 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS gl_lock_t NAME = { { 0, -1 } };
+    STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+    { { 0, -1 } }
 # define gl_lock_init(NAME) \
     glthread_lock_init (&NAME)
 # define gl_lock_lock(NAME) \
@@ -554,7 +975,9 @@ typedef struct
 # define gl_rwlock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_rwlock_t NAME;
 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS gl_rwlock_t NAME = { { 0, -1 } };
+    STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+    { { 0, -1 } }
 # define gl_rwlock_init(NAME) \
     glthread_rwlock_init (&NAME)
 # define gl_rwlock_rdlock(NAME) \
@@ -588,7 +1011,9 @@ typedef struct
 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
     STORAGECLASS gl_recursive_lock_t NAME;
 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
-    STORAGECLASS gl_recursive_lock_t NAME = { { 0, -1 }, 0, 0 };
+    STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+    { { 0, -1 }, 0, 0 }
 # define gl_recursive_lock_init(NAME) \
     glthread_recursive_lock_init (&NAME)
 # define gl_recursive_lock_lock(NAME) \
@@ -602,6 +1027,25 @@ extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
 
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef struct
+        {
+          volatile int inited;
+          volatile long started;
+          CRITICAL_SECTION lock;
+        }
+        gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+    STORAGECLASS gl_once_t NAME = { -1, -1 };
+# define gl_once(NAME, INITFUNCTION) \
+    glthread_once (&NAME, INITFUNCTION)
+extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
+
+# ifdef __cplusplus
+}
+# endif
+
 #endif
 
 /* ========================================================================= */
@@ -618,6 +1062,7 @@ typedef int gl_lock_t;
 # define gl_lock_init(NAME)
 # define gl_lock_lock(NAME)
 # define gl_lock_unlock(NAME)
+# define gl_lock_destroy(NAME)
 
 /* ------------------------- gl_rwlock_t datatype ------------------------- */
 
@@ -628,6 +1073,7 @@ typedef int gl_rwlock_t;
 # define gl_rwlock_rdlock(NAME)
 # define gl_rwlock_wrlock(NAME)
 # define gl_rwlock_unlock(NAME)
+# define gl_rwlock_destroy(NAME)
 
 /* --------------------- gl_recursive_lock_t datatype --------------------- */
 
@@ -637,5 +1083,26 @@ typedef int gl_recursive_lock_t;
 # define gl_recursive_lock_init(NAME)
 # define gl_recursive_lock_lock(NAME)
 # define gl_recursive_lock_unlock(NAME)
+# define gl_recursive_lock_destroy(NAME)
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef int gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+    STORAGECLASS gl_once_t NAME = 0;
+# define gl_once(NAME, INITFUNCTION) \
+    do                       \
+      {                      \
+        if (NAME == 0)       \
+          {                  \
+            NAME = ~ 0;      \
+            INITFUNCTION (); \
+          }                  \
+      }                      \
+    while (0)
 
 #endif
+
+/* ========================================================================= */
+
+#endif /* _LOCK_H */