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