Yesterday's changes.
[gnulib.git] / lib / lock.h
index 9ca33de..be99139 100644 (file)
      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>
 
+# 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,7 +140,9 @@ 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 ()
 # define gl_lock_lock(NAME) \
@@ -138,7 +162,9 @@ 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 ()
 #   define gl_rwlock_rdlock(NAME) \
@@ -162,7 +188,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, 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)
 #   define gl_rwlock_rdlock(NAME) \
@@ -195,8 +223,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 = \
-      { 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)
 # define gl_rwlock_rdlock(NAME) \
@@ -224,12 +253,14 @@ 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 ()
@@ -252,8 +283,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 = \
-        { 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)
 #   define gl_recursive_lock_lock(NAME) \
@@ -284,8 +316,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 = \
-       { 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)
 #  define gl_recursive_lock_lock(NAME) \
@@ -301,6 +334,28 @@ 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);
+
 #endif
 
 /* ========================================================================= */
@@ -322,6 +377,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,7 +394,9 @@ 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 ()
 # define gl_lock_lock(NAME) \
@@ -354,7 +412,9 @@ 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 ()
 #  define gl_rwlock_rdlock(NAME) \
@@ -373,7 +433,9 @@ 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 ()
 #  define gl_recursive_lock_lock(NAME) \
@@ -383,6 +445,30 @@ typedef pth_mutex_t gl_recursive_lock_t;
 #  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);
+
 #endif
 
 /* ========================================================================= */
@@ -425,7 +511,9 @@ 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 ()
 # define gl_lock_lock(NAME) \
@@ -441,7 +529,9 @@ 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 ()
 # define gl_rwlock_rdlock(NAME) \
@@ -468,7 +558,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 = { 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)
 # define gl_recursive_lock_lock(NAME) \
@@ -482,6 +574,33 @@ 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);
+
 #endif
 
 /* ========================================================================= */
@@ -514,7 +633,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 +675,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 +711,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 +727,21 @@ 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));
+
 #endif
 
 /* ========================================================================= */
@@ -638,4 +778,24 @@ typedef int gl_recursive_lock_t;
 # define gl_recursive_lock_lock(NAME)
 # define gl_recursive_lock_unlock(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 */