root/maint/gnulib/lib/glthread/cond.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. gl_cond_timedwait_func

   1 /* Condition variables for multithreading.
   2    Copyright (C) 2005-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 2.1 of the
   7    License, or (at your option) any later version.
   8 
   9    This file is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 /* Written by Yoann Vandoorselaere <yoann@prelude-ids.org>, 2008.
  18    Based on Bruno Haible <bruno@clisp.org> lock.h */
  19 
  20 /*
  21    Condition variables can be used for waiting until a condition
  22    becomes true. In this respect, they are similar to wait queues. But
  23    contrary to wait queues, condition variables have different
  24    semantics that allows events to be lost when there is no thread
  25    waiting for them.
  26 
  27    Condition variable:
  28      Type:                gl_cond_t
  29      Declaration:         gl_cond_define(extern, name)
  30      Initializer:         gl_cond_define_initialized(, name)
  31      Initialization:      gl_cond_init (name);
  32      Waiting:             gl_cond_wait (name, lock);
  33      Timed wait:          bool timedout = gl_cond_timedwait (name, lock, abstime);
  34                           where lock is a gl_lock_t variable (cf. <glthread/lock.h>)
  35      Signaling:           gl_cond_signal (name);
  36      Broadcasting:        gl_cond_broadcast (name);
  37      De-initialization:   gl_cond_destroy (name);
  38    Equivalent functions with control of error handling:
  39      Initialization:      err = glthread_cond_init (&name);
  40      Waiting:             err = glthread_cond_wait (&name);
  41      Timed wait:          err = glthread_cond_timedwait (&name, &lock, abstime);
  42      Signaling:           err = glthread_cond_signal (&name);
  43      Broadcasting:        err = glthread_cond_broadcast (&name);
  44      De-initialization:   err = glthread_cond_destroy (&name);
  45 */
  46 
  47 
  48 #ifndef _GLTHREAD_COND_H
  49 #define _GLTHREAD_COND_H
  50 
  51 #include <errno.h>
  52 #include <stdbool.h>
  53 #include <stdlib.h>
  54 #include <time.h>
  55 
  56 #include "glthread/lock.h"
  57 
  58 #if !defined c11_threads_in_use
  59 # if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
  60 #  define c11_threads_in_use() 1
  61 # elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
  62 #  include <threads.h>
  63 #  pragma weak thrd_exit
  64 #  define c11_threads_in_use() (thrd_exit != NULL)
  65 # else
  66 #  define c11_threads_in_use() 0
  67 # endif
  68 #endif
  69 
  70 #ifndef _GL_INLINE_HEADER_BEGIN
  71  #error "Please include config.h first."
  72 #endif
  73 
  74 _GL_INLINE_HEADER_BEGIN
  75 #ifndef _GLTHREAD_COND_INLINE
  76 # define _GLTHREAD_COND_INLINE _GL_INLINE
  77 #endif
  78 
  79 /* ========================================================================= */
  80 
  81 #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
  82 
  83 /* Use the ISO C threads library.  */
  84 
  85 # include <threads.h>
  86 
  87 # ifdef __cplusplus
  88 extern "C" {
  89 # endif
  90 
  91 /* -------------------------- gl_cond_t datatype -------------------------- */
  92 
  93 typedef struct
  94         {
  95           int volatile init_needed;
  96           once_flag init_once;
  97           void (*init_func) (void);
  98           cnd_t condition;
  99         }
 100         gl_cond_t;
 101 # define gl_cond_define(STORAGECLASS, NAME) \
 102     STORAGECLASS gl_cond_t NAME;
 103 # define gl_cond_define_initialized(STORAGECLASS, NAME) \
 104     static void _atomic_init_##NAME (void);       \
 105     STORAGECLASS gl_cond_t NAME =                 \
 106       { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
 107     static void _atomic_init_##NAME (void)        \
 108     {                                             \
 109       if (glthread_cond_init (&(NAME)))           \
 110         abort ();                                 \
 111     }
 112 extern int glthread_cond_init (gl_cond_t *condition);
 113 extern int glthread_cond_wait (gl_cond_t *condition, gl_lock_t *lock);
 114 extern int glthread_cond_timedwait (gl_cond_t *condition, gl_lock_t *lock,
 115                                     const struct timespec *abstime);
 116 extern int glthread_cond_signal (gl_cond_t *condition);
 117 extern int glthread_cond_broadcast (gl_cond_t *condition);
 118 extern int glthread_cond_destroy (gl_cond_t *condition);
 119 
 120 # ifdef __cplusplus
 121 }
 122 # endif
 123 
 124 #endif
 125 
 126 /* ========================================================================= */
 127 
 128 #if USE_POSIX_THREADS
 129 
 130 /* Use the POSIX threads library.  */
 131 
 132 # include <pthread.h>
 133 
 134 # ifdef __cplusplus
 135 extern "C" {
 136 # endif
 137 
 138 # if PTHREAD_IN_USE_DETECTION_HARD
 139 
 140 /* The pthread_in_use() detection needs to be done at runtime.  */
 141 #  define pthread_in_use() \
 142      glthread_in_use ()
 143 extern int glthread_in_use (void);
 144 
 145 # endif
 146 
 147 # if USE_POSIX_THREADS_WEAK
 148 
 149 /* Use weak references to the POSIX threads library.  */
 150 
 151 /* Weak references avoid dragging in external libraries if the other parts
 152    of the program don't use them.  Here we use them, because we don't want
 153    every program that uses libintl to depend on libpthread.  This assumes
 154    that libpthread would not be loaded after libintl; i.e. if libintl is
 155    loaded first, by an executable that does not depend on libpthread, and
 156    then a module is dynamically loaded that depends on libpthread, libintl
 157    will not be multithread-safe.  */
 158 
 159 /* The way to test at runtime whether libpthread is present is to test
 160    whether a function pointer's value, such as &pthread_mutex_init, is
 161    non-NULL.  However, some versions of GCC have a bug through which, in
 162    PIC mode, &foo != NULL always evaluates to true if there is a direct
 163    call to foo(...) in the same function.  To avoid this, we test the
 164    address of a function in libpthread that we don't use.  */
 165 
 166 #  pragma weak pthread_cond_init
 167 #  pragma weak pthread_cond_wait
 168 #  pragma weak pthread_cond_timedwait
 169 #  pragma weak pthread_cond_signal
 170 #  pragma weak pthread_cond_broadcast
 171 #  pragma weak pthread_cond_destroy
 172 #  ifndef pthread_self
 173 #   pragma weak pthread_self
 174 #  endif
 175 
 176 #  if !PTHREAD_IN_USE_DETECTION_HARD
 177 #   pragma weak pthread_mutexattr_gettype
 178 #   define pthread_in_use() \
 179       (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
 180 #  endif
 181 
 182 # else
 183 
 184 #  if !PTHREAD_IN_USE_DETECTION_HARD
 185 #   define pthread_in_use() 1
 186 #  endif
 187 
 188 # endif
 189 
 190 /* -------------------------- gl_cond_t datatype -------------------------- */
 191 
 192 typedef pthread_cond_t gl_cond_t;
 193 # define gl_cond_define(STORAGECLASS, NAME) \
 194     STORAGECLASS gl_cond_t NAME;
 195 # define gl_cond_define_initialized(STORAGECLASS, NAME) \
 196     STORAGECLASS gl_cond_t NAME = gl_cond_initializer;
 197 # define gl_cond_initializer \
 198     PTHREAD_COND_INITIALIZER
 199 # define glthread_cond_init(COND) \
 200     (pthread_in_use () ? pthread_cond_init (COND, NULL) : 0)
 201 # define glthread_cond_wait(COND, LOCK) \
 202     (pthread_in_use () ? pthread_cond_wait (COND, LOCK) : 0)
 203 # define glthread_cond_timedwait(COND, LOCK, ABSTIME) \
 204     (pthread_in_use () ? pthread_cond_timedwait (COND, LOCK, ABSTIME) : 0)
 205 # define glthread_cond_signal(COND) \
 206     (pthread_in_use () ? pthread_cond_signal (COND) : 0)
 207 # define glthread_cond_broadcast(COND) \
 208     (pthread_in_use () ? pthread_cond_broadcast (COND) : 0)
 209 # define glthread_cond_destroy(COND) \
 210     (pthread_in_use () ? pthread_cond_destroy (COND) : 0)
 211 
 212 # ifdef __cplusplus
 213 }
 214 # endif
 215 
 216 #endif
 217 
 218 /* ========================================================================= */
 219 
 220 #if USE_WINDOWS_THREADS
 221 
 222 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
 223 # include <windows.h>
 224 
 225 # include "windows-cond.h"
 226 
 227 # ifdef __cplusplus
 228 extern "C" {
 229 # endif
 230 
 231 /* -------------------------- gl_cond_t datatype -------------------------- */
 232 
 233 typedef glwthread_cond_t gl_cond_t;
 234 # define gl_cond_define(STORAGECLASS, NAME) \
 235     STORAGECLASS gl_cond_t NAME;
 236 # define gl_cond_define_initialized(STORAGECLASS, NAME) \
 237     STORAGECLASS gl_cond_t NAME = gl_cond_initializer;
 238 # define gl_cond_initializer \
 239     GLWTHREAD_COND_INIT
 240 # define glthread_cond_init(COND) \
 241     glwthread_cond_init (COND)
 242 # define glthread_cond_wait(COND, LOCK) \
 243     glwthread_cond_wait (COND, LOCK, \
 244                          (int (*) (void *)) glwthread_mutex_lock, \
 245                          (int (*) (void *)) glwthread_mutex_unlock)
 246 # define glthread_cond_timedwait(COND, LOCK, ABSTIME) \
 247     glwthread_cond_timedwait (COND, LOCK, \
 248                               (int (*) (void *)) glwthread_mutex_lock, \
 249                               (int (*) (void *)) glwthread_mutex_unlock, \
 250                               ABSTIME)
 251 # define glthread_cond_signal(COND) \
 252     glwthread_cond_signal (COND)
 253 # define glthread_cond_broadcast(COND) \
 254     glwthread_cond_broadcast (COND)
 255 # define glthread_cond_destroy(COND) \
 256     glwthread_cond_destroy (COND)
 257 
 258 # ifdef __cplusplus
 259 }
 260 # endif
 261 
 262 #endif
 263 
 264 /* ========================================================================= */
 265 
 266 #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
 267 
 268 /* Provide dummy implementation if threads are not supported.  */
 269 
 270 typedef int gl_cond_t;
 271 # define gl_cond_define(STORAGECLASS, NAME)
 272 # define gl_cond_define_initialized(STORAGECLASS, NAME)
 273 # define glthread_cond_init(COND) 0
 274 # define glthread_cond_wait(COND, LOCK) 0
 275 # define glthread_cond_timedwait(COND, LOCK, ABSTIME) 0
 276 # define glthread_cond_signal(COND) 0
 277 # define glthread_cond_broadcast(COND) 0
 278 # define glthread_cond_destroy(COND) 0
 279 
 280 #endif
 281 
 282 /* ========================================================================= */
 283 
 284 /* Macros with built-in error handling.  */
 285 
 286 #ifdef __cplusplus
 287 extern "C" {
 288 #endif
 289 
 290 #define gl_cond_init(COND)             \
 291    do                                  \
 292      {                                 \
 293        if (glthread_cond_init (&COND)) \
 294          abort ();                     \
 295      }                                 \
 296    while (0)
 297 #define gl_cond_wait(COND, LOCK)              \
 298    do                                         \
 299      {                                        \
 300        if (glthread_cond_wait (&COND, &LOCK)) \
 301          abort ();                            \
 302      }                                        \
 303    while (0)
 304 #define gl_cond_timedwait(COND, LOCK, ABSTIME) \
 305   gl_cond_timedwait_func (&COND, &LOCK, ABSTIME)
 306 _GLTHREAD_COND_INLINE bool
 307 gl_cond_timedwait_func (gl_cond_t *cond, gl_lock_t *lock, struct timespec *abstime)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309   int err = glthread_cond_timedwait (cond, lock, abstime);
 310   if (err == ETIMEDOUT)
 311     return true;
 312   if (err != 0)
 313     abort ();
 314   return false;
 315 }
 316 #define gl_cond_signal(COND)             \
 317    do                                    \
 318      {                                   \
 319        if (glthread_cond_signal (&COND)) \
 320          abort ();                       \
 321      }                                   \
 322    while (0)
 323 #define gl_cond_broadcast(COND)             \
 324    do                                       \
 325      {                                      \
 326        if (glthread_cond_broadcast (&COND)) \
 327          abort ();                          \
 328      }                                      \
 329    while (0)
 330 #define gl_cond_destroy(COND)             \
 331    do                                     \
 332      {                                    \
 333        if (glthread_cond_destroy (&COND)) \
 334          abort ();                        \
 335      }                                    \
 336    while (0)
 337 
 338 #ifdef __cplusplus
 339 }
 340 #endif
 341 
 342 _GL_INLINE_HEADER_END
 343 
 344 #endif /* _GLTHREAD_COND_H */

/* [previous][next][first][last][top][bottom][index][help] */