Add support for MacOS X ACLs.
[gnulib.git] / lib / tls.h
1 /* Thread-local storage in multithreaded situations.
2    Copyright (C) 2005, 2007 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 3 of the License, or
7    (at your option) 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, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2005.  */
18
19 /* This file contains thread-local storage primitives for use with a given
20    thread library.  It does not contain primitives for creating threads or
21    for other multithreading primitives.
22
23    Type:                      gl_tls_key_t
24    Initialization:            gl_tls_key_init (name, destructor);
25    Getting per-thread value:  gl_tls_get (name)
26    Setting per-thread value:  gl_tls_set (name, pointer);
27    De-initialization:         gl_tls_key_destroy (name);
28
29    A per-thread value is of type 'void *'.
30
31    A destructor is a function pointer of type 'void (*) (void *)', called
32    when a thread exits, and taking the last per-thread value as argument.  It
33    is unspecified whether the destructor function is called when the last
34    per-thread value is NULL.  On some platforms, the destructor function is
35    not called at all.
36 */
37
38
39 #ifndef _TLS_H
40 #define _TLS_H
41
42 /* ========================================================================= */
43
44 #if USE_POSIX_THREADS
45
46 /* Use the POSIX threads library.  */
47
48 # include <pthread.h>
49 # include <stdlib.h>
50
51 # if PTHREAD_IN_USE_DETECTION_HARD
52
53 /* The pthread_in_use() detection needs to be done at runtime.  */
54 #  define pthread_in_use() \
55      glthread_in_use ()
56 extern int glthread_in_use (void);
57
58 # endif
59
60 # if USE_POSIX_THREADS_WEAK
61
62 /* Use weak references to the POSIX threads library.  */
63
64 #  pragma weak pthread_key_create
65 #  pragma weak pthread_getspecific
66 #  pragma weak pthread_setspecific
67 #  pragma weak pthread_key_delete
68 #  ifndef pthread_self
69 #   pragma weak pthread_self
70 #  endif
71
72 #  if !PTHREAD_IN_USE_DETECTION_HARD
73 #   pragma weak pthread_cancel
74 #   define pthread_in_use() (pthread_cancel != NULL)
75 #  endif
76
77 # else
78
79 #  if !PTHREAD_IN_USE_DETECTION_HARD
80 #   define pthread_in_use() 1
81 #  endif
82
83 # endif
84
85 /* ------------------------- gl_tls_key_t datatype ------------------------- */
86
87 typedef union
88         {
89           void *singlethread_value;
90           pthread_key_t key;
91         }
92         gl_tls_key_t;
93 # define gl_tls_key_init(NAME, DESTRUCTOR) \
94     do                                                             \
95       {                                                            \
96         if (pthread_in_use ())                                     \
97           {                                                        \
98             if (pthread_key_create (&(NAME).key, DESTRUCTOR) != 0) \
99               abort ();                                            \
100           }                                                        \
101         else                                                       \
102           (NAME).singlethread_value = NULL;                        \
103       }                                                            \
104     while (0)
105 # define gl_tls_get(NAME) \
106     (pthread_in_use ()                  \
107      ? pthread_getspecific ((NAME).key) \
108      : (NAME).singlethread_value)
109 # define gl_tls_set(NAME, POINTER) \
110     do                                                            \
111       {                                                           \
112         if (pthread_in_use ())                                    \
113           {                                                       \
114             if (pthread_setspecific ((NAME).key, (POINTER)) != 0) \
115               abort ();                                           \
116           }                                                       \
117         else                                                      \
118           (NAME).singlethread_value = (POINTER);                  \
119       }                                                           \
120     while (0)
121 # define gl_tls_key_destroy(NAME) \
122     do                                                                 \
123       {                                                                \
124         if (pthread_in_use () && pthread_key_delete ((NAME).key) != 0) \
125           abort ();                                                    \
126       }                                                                \
127     while (0)
128
129 #endif
130
131 /* ========================================================================= */
132
133 #if USE_PTH_THREADS
134
135 /* Use the GNU Pth threads library.  */
136
137 # include <pth.h>
138 # include <stdlib.h>
139
140 # if USE_PTH_THREADS_WEAK
141
142 /* Use weak references to the GNU Pth threads library.  */
143
144 #  pragma weak pth_key_create
145 #  pragma weak pth_key_getdata
146 #  pragma weak pth_key_setdata
147 #  pragma weak pth_key_delete
148
149 #  pragma weak pth_cancel
150 #  define pth_in_use() (pth_cancel != NULL)
151
152 # else
153
154 #  define pth_in_use() 1
155
156 # endif
157
158 /* ------------------------- gl_tls_key_t datatype ------------------------- */
159
160 typedef union
161         {
162           void *singlethread_value;
163           pth_key_t key;
164         }
165         gl_tls_key_t;
166 # define gl_tls_key_init(NAME, DESTRUCTOR) \
167     do                                                     \
168       {                                                    \
169         if (pth_in_use ())                                 \
170           {                                                \
171             if (!pth_key_create (&(NAME).key, DESTRUCTOR)) \
172               abort ();                                    \
173           }                                                \
174         else                                               \
175           (NAME).singlethread_value = NULL;                \
176       }                                                    \
177     while (0)
178 # define gl_tls_get(NAME) \
179     (pth_in_use ()                  \
180      ? pth_key_getdata ((NAME).key) \
181      : (NAME).singlethread_value)
182 # define gl_tls_set(NAME, POINTER) \
183     do                                                    \
184       {                                                   \
185         if (pth_in_use ())                                \
186           {                                               \
187             if (!pth_key_setdata ((NAME).key, (POINTER))) \
188               abort ();                                   \
189           }                                               \
190         else                                              \
191           (NAME).singlethread_value = (POINTER);          \
192       }                                                   \
193     while (0)
194 # define gl_tls_key_destroy(NAME) \
195     do                                                     \
196       {                                                    \
197         if (pth_in_use () && !pth_key_delete ((NAME).key)) \
198           abort ();                                        \
199       }                                                    \
200     while (0)
201
202 #endif
203
204 /* ========================================================================= */
205
206 #if USE_SOLARIS_THREADS
207
208 /* Use the old Solaris threads library.  */
209
210 # include <thread.h>
211 # include <stdlib.h>
212
213 # if USE_SOLARIS_THREADS_WEAK
214
215 /* Use weak references to the old Solaris threads library.  */
216
217 #  pragma weak thr_keycreate
218 #  pragma weak thr_getspecific
219 #  pragma weak thr_setspecific
220
221 #  pragma weak thr_suspend
222 #  define thread_in_use() (thr_suspend != NULL)
223
224 # else
225
226 #  define thread_in_use() 1
227
228 # endif
229
230 /* ------------------------- gl_tls_key_t datatype ------------------------- */
231
232 typedef union
233         {
234           void *singlethread_value;
235           thread_key_t key;
236         }
237         gl_tls_key_t;
238 # define gl_tls_key_init(NAME, DESTRUCTOR) \
239     do                                                        \
240       {                                                       \
241         if (thread_in_use ())                                 \
242           {                                                   \
243             if (thr_keycreate (&(NAME).key, DESTRUCTOR) != 0) \
244               abort ();                                       \
245           }                                                   \
246         else                                                  \
247           (NAME).singlethread_value = NULL;                   \
248       }                                                       \
249     while (0)
250 # define gl_tls_get(NAME) \
251     (thread_in_use ()                \
252      ? glthread_tls_get ((NAME).key) \
253      : (NAME).singlethread_value)
254 extern void *glthread_tls_get (thread_key_t key);
255 # define gl_tls_set(NAME, POINTER) \
256     do                                                        \
257       {                                                       \
258         if (thread_in_use ())                                 \
259           {                                                   \
260             if (thr_setspecific ((NAME).key, (POINTER)) != 0) \
261               abort ();                                       \
262           }                                                   \
263         else                                                  \
264           (NAME).singlethread_value = (POINTER);              \
265       }                                                       \
266     while (0)
267 # define gl_tls_key_destroy(NAME) \
268     /* Unsupported.  */ \
269     (void)0
270
271 #endif
272
273 /* ========================================================================= */
274
275 #if USE_WIN32_THREADS
276
277 # include <windows.h>
278
279 /* ------------------------- gl_tls_key_t datatype ------------------------- */
280
281 typedef DWORD gl_tls_key_t;
282 # define gl_tls_key_init(NAME, DESTRUCTOR) \
283     /* The destructor is unsupported.  */    \
284     do                                           \
285       {                                          \
286         if (((NAME) = TlsAlloc ()) == (DWORD)-1) \
287           abort ();                              \
288       }                                          \
289     while (0)
290 # define gl_tls_get(NAME) \
291     TlsGetValue (NAME)
292 # define gl_tls_set(NAME, POINTER) \
293     do                                    \
294       {                                   \
295         if (!TlsSetValue (NAME, POINTER)) \
296           abort ();                       \
297       }                                   \
298     while (0)
299 # define gl_tls_key_destroy(NAME) \
300     do                       \
301       {                      \
302         if (!TlsFree (NAME)) \
303           abort ();          \
304       }                      \
305     while (0)
306
307 #endif
308
309 /* ========================================================================= */
310
311 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
312
313 /* Provide dummy implementation if threads are not supported.  */
314
315 /* ------------------------- gl_tls_key_t datatype ------------------------- */
316
317 typedef struct
318         {
319           void *singlethread_value;
320         }
321         gl_tls_key_t;
322 # define gl_tls_key_init(NAME, DESTRUCTOR) \
323     (NAME).singlethread_value = NULL
324 # define gl_tls_get(NAME) \
325     (NAME).singlethread_value
326 # define gl_tls_set(NAME, POINTER) \
327     (NAME).singlethread_value = (POINTER)
328 # define gl_tls_key_destroy(NAME) \
329     (void)0
330
331 #endif
332
333 /* ========================================================================= */
334
335 #endif /* _TLS_H */