Fix syntax errors in C++ mode.
[gnulib.git] / lib / glthread / thread.h
1 /* Creating and controlling threads.
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 Bruno Haible <bruno@clisp.org>, 2005.
19    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
20    gthr-win32.h.  */
21
22 /* This file contains primitives for creating and controlling threads.
23
24    Thread data type: gl_thread_t.
25
26    Creating a thread:
27        thread = gl_thread_create (func, arg);
28    Or with control of error handling:
29        err = glthread_create (&thread, func, arg);
30        extern int glthread_create (gl_thread_t *result,
31                                    void *(*func) (void *), void *arg);
32
33    Querying and changing the signal mask of a thread (not supported on all
34    platforms):
35        gl_thread_sigmask (how, newmask, oldmask);
36    Or with control of error handling:
37        err = glthread_sigmask (how, newmask, oldmask);
38        extern int glthread_sigmask (int how, const sigset_t *newmask, sigset_t *oldmask);
39
40    Waiting for termination of another thread:
41        gl_thread_join (thread, &return_value);
42    Or with control of error handling:
43        err = glthread_join (thread, &return_value);
44        extern int glthread_join (gl_thread_t thread, void **return_value_ptr);
45
46    Getting a reference to the current thread:
47        current = gl_thread_self ();
48        extern gl_thread_t gl_thread_self (void);
49
50    Terminating the current thread:
51        gl_thread_exit (return_value);
52        extern void gl_thread_exit (void *return_value) __attribute__ ((noreturn));
53
54    Requesting custom code to be executed at fork() time(not supported on all
55    platforms):
56        gl_thread_atfork (prepare_func, parent_func, child_func);
57    Or with control of error handling:
58        err = glthread_atfork (prepare_func, parent_func, child_func);
59        extern int glthread_atfork (void (*prepare_func) (void),
60                                    void (*parent_func) (void),
61                                    void (*child_func) (void));
62    Note that even on platforms where this is supported, use of fork() and
63    threads together is problematic, see
64      <http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00062.html>
65  */
66
67
68 #ifndef _GLTHREAD_THREAD_H
69 #define _GLTHREAD_THREAD_H
70
71 #include <errno.h>
72 #include <stdlib.h>
73
74 /* ========================================================================= */
75
76 #if USE_POSIX_THREADS
77
78 /* Use the POSIX threads library.  */
79
80 # include <pthread.h>
81
82 # ifdef __cplusplus
83 extern "C" {
84 # endif
85
86 # if PTHREAD_IN_USE_DETECTION_HARD
87
88 /* The pthread_in_use() detection needs to be done at runtime.  */
89 #  define pthread_in_use() \
90      glthread_in_use ()
91 extern int glthread_in_use (void);
92
93 # endif
94
95 # if USE_POSIX_THREADS_WEAK
96
97 /* Use weak references to the POSIX threads library.  */
98
99 /* Weak references avoid dragging in external libraries if the other parts
100    of the program don't use them.  Here we use them, because we don't want
101    every program that uses libintl to depend on libpthread.  This assumes
102    that libpthread would not be loaded after libintl; i.e. if libintl is
103    loaded first, by an executable that does not depend on libpthread, and
104    then a module is dynamically loaded that depends on libpthread, libintl
105    will not be multithread-safe.  */
106
107 /* The way to test at runtime whether libpthread is present is to test
108    whether a function pointer's value, such as &pthread_mutex_init, is
109    non-NULL.  However, some versions of GCC have a bug through which, in
110    PIC mode, &foo != NULL always evaluates to true if there is a direct
111    call to foo(...) in the same function.  To avoid this, we test the
112    address of a function in libpthread that we don't use.  */
113
114 #  pragma weak pthread_create
115 #  pragma weak pthread_sigmask
116 #  pragma weak pthread_join
117 #  ifndef pthread_self
118 #   pragma weak pthread_self
119 #  endif
120 #  pragma weak pthread_exit
121 #  if HAVE_PTHREAD_ATFORK
122 #   pragma weak pthread_atfork
123 #  endif
124
125 #  if !PTHREAD_IN_USE_DETECTION_HARD
126 #   pragma weak pthread_cancel
127 #   define pthread_in_use() (pthread_cancel != NULL)
128 #  endif
129
130 # else
131
132 #  if !PTHREAD_IN_USE_DETECTION_HARD
133 #   define pthread_in_use() 1
134 #  endif
135
136 # endif
137
138 /* -------------------------- gl_thread_t datatype -------------------------- */
139
140 typedef pthread_t gl_thread_t;
141 # define glthread_create(THREADP, FUNC, ARG) \
142     (pthread_in_use () ? pthread_create (THREADP, NULL, FUNC, ARG) : ENOSYS)
143 # define glthread_sigmask(HOW, SET, OSET) \
144     (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
145 # define glthread_join(THREAD, RETVALP) \
146     (pthread_in_use () ? pthread_join (THREAD, RETVALP) : 0)
147 # define gl_thread_self() \
148     (pthread_in_use () ? (void *) pthread_self () : NULL)
149 # define gl_thread_exit(RETVAL) \
150     (pthread_in_use () ? pthread_exit (RETVAL) : 0)
151
152 # if HAVE_PTHREAD_ATFORK
153 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \
154      (pthread_in_use () ? pthread_atfork (PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) : 0)
155 # else
156 #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
157 # endif
158
159 # ifdef __cplusplus
160 }
161 # endif
162
163 #endif
164
165 /* ========================================================================= */
166
167 #if USE_PTH_THREADS
168
169 /* Use the GNU Pth threads library.  */
170
171 # include <pth.h>
172
173 # ifdef __cplusplus
174 extern "C" {
175 # endif
176
177 # if USE_PTH_THREADS_WEAK
178
179 /* Use weak references to the GNU Pth threads library.  */
180
181 #  pragma weak pth_spawn
182 #  pragma weak pth_sigmask
183 #  pragma weak pth_join
184 #  pragma weak pth_self
185 #  pragma weak pth_exit
186
187 #  pragma weak pth_cancel
188 #  define pth_in_use() (pth_cancel != NULL)
189
190 # else
191
192 #  define pth_in_use() 1
193
194 # endif
195 /* -------------------------- gl_thread_t datatype -------------------------- */
196
197 typedef pth_t gl_thread_t;
198 # define glthread_create(THREADP, FUNC, ARG) \
199     (pth_in_use () ? ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno) : 0)
200 # define glthread_sigmask(HOW, SET, OSET) \
201     (pth_in_use () && !pth_sigmask (HOW, SET, OSET) ? errno : 0)
202 # define glthread_join(THREAD, RETVALP) \
203     (pth_in_use () && !pth_join (THREAD, RETVALP) ? errno : 0)
204 # define gl_thread_self() \
205     (pth_in_use () ? (void *) pth_self () : 0)
206 # define gl_thread_exit(RETVAL) \
207     (pth_in_use () ? pth_exit (RETVAL) : 0)
208 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
209
210 # ifdef __cplusplus
211 }
212 # endif
213
214 #endif
215
216 /* ========================================================================= */
217
218 #if USE_SOLARIS_THREADS
219
220 /* Use the old Solaris threads library.  */
221
222 # include <thread.h>
223 # include <synch.h>
224
225 # ifdef __cplusplus
226 extern "C" {
227 # endif
228
229 # if USE_SOLARIS_THREADS_WEAK
230
231 /* Use weak references to the old Solaris threads library.  */
232
233 #  pragma weak thr_create
234 #  pragma weak thr_join
235 #  pragma weak thr_self
236 #  pragma weak thr_exit
237
238 #  pragma weak thr_suspend
239 #  define thread_in_use() (thr_suspend != NULL)
240
241 # else
242
243 #  define thread_in_use() 1
244
245 # endif
246
247 /* -------------------------- gl_thread_t datatype -------------------------- */
248
249 typedef thread_t gl_thread_t;
250 # define glthread_create(THREADP, FUNC, ARG) \
251     (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0)
252 # define glthread_sigmask(HOW, SET, OSET) \
253     (pthread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
254 # define glthread_join(THREAD, RETVALP) \
255     (pthread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0)
256 # define gl_thread_self() \
257     (pthread_in_use () ? (void *) thr_self () : 0)
258 # define gl_thread_exit(RETVAL) \
259     (pthread_in_use () ? thr_exit (RETVAL) : 0)
260 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
261
262 # ifdef __cplusplus
263 }
264 # endif
265
266 #endif
267
268 /* ========================================================================= */
269
270 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
271
272 /* Provide dummy implementation if threads are not supported.  */
273
274 typedef int gl_thread_t;
275 # define glthread_create(THREADP, FUNC, ARG) ENOSYS
276 # define glthread_sigmask(HOW, SET, OSET) 0
277 # define glthread_join(THREAD, RETVALP) 0
278 # define gl_thread_self() NULL
279 # define gl_thread_exit(RETVAL) 0
280 # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0
281
282 #endif
283
284 /* ========================================================================= */
285
286 /* Macros with built-in error handling.  */
287
288 #ifdef __cplusplus
289 extern "C" {
290 #endif
291
292 static inline gl_thread_t
293 gl_thread_create (void *(*func) (void *arg), void *arg)
294 {
295   gl_thread_t thread;
296   int ret;
297
298   ret = glthread_create (&thread, func, arg);
299   if (ret != 0)
300     abort ();
301   return thread;
302 }
303 #define gl_thread_sigmask(HOW, SET, OSET)     \
304    do                                         \
305      {                                        \
306        if (glthread_sigmask (HOW, SET, OSET)) \
307          abort ();                            \
308      }                                        \
309    while (0)
310 #define gl_thread_join(THREAD, RETVAL)     \
311    do                                      \
312      {                                     \
313        if (glthread_join (THREAD, RETVAL)) \
314          abort ();                         \
315      }                                     \
316    while (0)
317 #define gl_thread_atfork(PREPARE, PARENT, CHILD)     \
318    do                                                \
319      {                                               \
320        if (glthread_atfork (PREPARE, PARENT, CHILD)) \
321          abort ();                                   \
322      }                                               \
323    while (0)
324
325 #ifdef __cplusplus
326 }
327 #endif
328
329 #endif /* _GLTHREAD_THREAD_H */