~ubuntu-branches/ubuntu/utopic/gettext/utopic

« back to all changes in this revision

Viewing changes to gettext-tools/libgettextpo/glthread/tls.h

  • Committer: Colin Watson
  • Date: 2010-08-01 21:36:08 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: cjwatson@canonical.com-20100801213608-yy7vkm8lpatep3ci
merge from Debian 0.18.1.1-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Thread-local storage in multithreaded situations.
 
2
   Copyright (C) 2005, 2007-2010 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
   Equivalent functions with control of error handling:
 
29
     Initialization:            err = glthread_tls_key_init (&name, destructor);
 
30
     Setting per-thread value:  err = glthread_tls_set (&name, pointer);
 
31
     De-initialization:         err = glthread_tls_key_destroy (&name);
 
32
 
 
33
   A per-thread value is of type 'void *'.
 
34
 
 
35
   A destructor is a function pointer of type 'void (*) (void *)', called
 
36
   when a thread exits, and taking the last per-thread value as argument.  It
 
37
   is unspecified whether the destructor function is called when the last
 
38
   per-thread value is NULL.  On some platforms, the destructor function is
 
39
   not called at all.
 
40
*/
 
41
 
 
42
 
 
43
#ifndef _TLS_H
 
44
#define _TLS_H
 
45
 
 
46
#include <errno.h>
 
47
#include <stdlib.h>
 
48
 
 
49
/* ========================================================================= */
 
50
 
 
51
#if USE_POSIX_THREADS
 
52
 
 
53
/* Use the POSIX threads library.  */
 
54
 
 
55
# include <pthread.h>
 
56
 
 
57
# if PTHREAD_IN_USE_DETECTION_HARD
 
58
 
 
59
/* The pthread_in_use() detection needs to be done at runtime.  */
 
60
#  define pthread_in_use() \
 
61
     glthread_in_use ()
 
62
extern int glthread_in_use (void);
 
63
 
 
64
# endif
 
65
 
 
66
# if USE_POSIX_THREADS_WEAK
 
67
 
 
68
/* Use weak references to the POSIX threads library.  */
 
69
 
 
70
#  pragma weak pthread_key_create
 
71
#  pragma weak pthread_getspecific
 
72
#  pragma weak pthread_setspecific
 
73
#  pragma weak pthread_key_delete
 
74
#  ifndef pthread_self
 
75
#   pragma weak pthread_self
 
76
#  endif
 
77
 
 
78
#  if !PTHREAD_IN_USE_DETECTION_HARD
 
79
#   pragma weak pthread_cancel
 
80
#   define pthread_in_use() (pthread_cancel != NULL)
 
81
#  endif
 
82
 
 
83
# else
 
84
 
 
85
#  if !PTHREAD_IN_USE_DETECTION_HARD
 
86
#   define pthread_in_use() 1
 
87
#  endif
 
88
 
 
89
# endif
 
90
 
 
91
/* ------------------------- gl_tls_key_t datatype ------------------------- */
 
92
 
 
93
typedef union
 
94
        {
 
95
          void *singlethread_value;
 
96
          pthread_key_t key;
 
97
        }
 
98
        gl_tls_key_t;
 
99
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
 
100
    (pthread_in_use ()                              \
 
101
     ? pthread_key_create (&(KEY)->key, DESTRUCTOR) \
 
102
     : ((KEY)->singlethread_value = NULL, 0))
 
103
# define gl_tls_get(NAME) \
 
104
    (pthread_in_use ()                  \
 
105
     ? pthread_getspecific ((NAME).key) \
 
106
     : (NAME).singlethread_value)
 
107
# define glthread_tls_set(KEY, POINTER) \
 
108
    (pthread_in_use ()                             \
 
109
     ? pthread_setspecific ((KEY)->key, (POINTER)) \
 
110
     : ((KEY)->singlethread_value = (POINTER), 0))
 
111
# define glthread_tls_key_destroy(KEY) \
 
112
    (pthread_in_use () ? pthread_key_delete ((KEY)->key) : 0)
 
113
 
 
114
#endif
 
115
 
 
116
/* ========================================================================= */
 
117
 
 
118
#if USE_PTH_THREADS
 
119
 
 
120
/* Use the GNU Pth threads library.  */
 
121
 
 
122
# include <pth.h>
 
123
 
 
124
# if USE_PTH_THREADS_WEAK
 
125
 
 
126
/* Use weak references to the GNU Pth threads library.  */
 
127
 
 
128
#  pragma weak pth_key_create
 
129
#  pragma weak pth_key_getdata
 
130
#  pragma weak pth_key_setdata
 
131
#  pragma weak pth_key_delete
 
132
 
 
133
#  pragma weak pth_cancel
 
134
#  define pth_in_use() (pth_cancel != NULL)
 
135
 
 
136
# else
 
137
 
 
138
#  define pth_in_use() 1
 
139
 
 
140
# endif
 
141
 
 
142
/* ------------------------- gl_tls_key_t datatype ------------------------- */
 
143
 
 
144
typedef union
 
145
        {
 
146
          void *singlethread_value;
 
147
          pth_key_t key;
 
148
        }
 
149
        gl_tls_key_t;
 
150
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
 
151
    (pth_in_use ()                                             \
 
152
     ? (!pth_key_create (&(KEY)->key, DESTRUCTOR) ? errno : 0) \
 
153
     : ((KEY)->singlethread_value = NULL, 0))
 
154
# define gl_tls_get(NAME) \
 
155
    (pth_in_use ()                  \
 
156
     ? pth_key_getdata ((NAME).key) \
 
157
     : (NAME).singlethread_value)
 
158
# define glthread_tls_set(KEY, POINTER) \
 
159
    (pth_in_use ()                                            \
 
160
     ? (!pth_key_setdata ((KEY)->key, (POINTER)) ? errno : 0) \
 
161
     : ((KEY)->singlethread_value = (POINTER), 0))
 
162
# define glthread_tls_key_destroy(KEY) \
 
163
    (pth_in_use ()                                \
 
164
     ? (!pth_key_delete ((KEY)->key) ? errno : 0) \
 
165
     : 0)
 
166
 
 
167
#endif
 
168
 
 
169
/* ========================================================================= */
 
170
 
 
171
#if USE_SOLARIS_THREADS
 
172
 
 
173
/* Use the old Solaris threads library.  */
 
174
 
 
175
# include <thread.h>
 
176
 
 
177
# if USE_SOLARIS_THREADS_WEAK
 
178
 
 
179
/* Use weak references to the old Solaris threads library.  */
 
180
 
 
181
#  pragma weak thr_keycreate
 
182
#  pragma weak thr_getspecific
 
183
#  pragma weak thr_setspecific
 
184
 
 
185
#  pragma weak thr_suspend
 
186
#  define thread_in_use() (thr_suspend != NULL)
 
187
 
 
188
# else
 
189
 
 
190
#  define thread_in_use() 1
 
191
 
 
192
# endif
 
193
 
 
194
/* ------------------------- gl_tls_key_t datatype ------------------------- */
 
195
 
 
196
typedef union
 
197
        {
 
198
          void *singlethread_value;
 
199
          thread_key_t key;
 
200
        }
 
201
        gl_tls_key_t;
 
202
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
 
203
    (thread_in_use ()                          \
 
204
     ? thr_keycreate (&(KEY)->key, DESTRUCTOR) \
 
205
     : ((KEY)->singlethread_value = NULL, 0))
 
206
# define gl_tls_get(NAME) \
 
207
    (thread_in_use ()                \
 
208
     ? glthread_tls_get_multithreaded ((NAME).key) \
 
209
     : (NAME).singlethread_value)
 
210
extern void *glthread_tls_get_multithreaded (thread_key_t key);
 
211
# define glthread_tls_set(KEY, POINTER) \
 
212
    (thread_in_use ()                              \
 
213
     ? thr_setspecific ((KEY)->key, (POINTER))     \
 
214
     : ((KEY)->singlethread_value = (POINTER), 0))
 
215
# define glthread_tls_key_destroy(KEY) \
 
216
    /* Unsupported.  */ \
 
217
    0
 
218
 
 
219
#endif
 
220
 
 
221
/* ========================================================================= */
 
222
 
 
223
#if USE_WIN32_THREADS
 
224
 
 
225
# include <windows.h>
 
226
 
 
227
/* ------------------------- gl_tls_key_t datatype ------------------------- */
 
228
 
 
229
typedef DWORD gl_tls_key_t;
 
230
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
 
231
    /* The destructor is unsupported.  */    \
 
232
    ((*(KEY) = TlsAlloc ()) == (DWORD)-1 ? EAGAIN : ((void) (DESTRUCTOR), 0))
 
233
# define gl_tls_get(NAME) \
 
234
    TlsGetValue (NAME)
 
235
# define glthread_tls_set(KEY, POINTER) \
 
236
    (!TlsSetValue (*(KEY), POINTER) ? EINVAL : 0)
 
237
# define glthread_tls_key_destroy(KEY) \
 
238
    (!TlsFree (*(KEY)) ? EINVAL : 0)
 
239
 
 
240
#endif
 
241
 
 
242
/* ========================================================================= */
 
243
 
 
244
#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
 
245
 
 
246
/* Provide dummy implementation if threads are not supported.  */
 
247
 
 
248
/* ------------------------- gl_tls_key_t datatype ------------------------- */
 
249
 
 
250
typedef struct
 
251
        {
 
252
          void *singlethread_value;
 
253
        }
 
254
        gl_tls_key_t;
 
255
# define glthread_tls_key_init(KEY, DESTRUCTOR) \
 
256
    ((KEY)->singlethread_value = NULL, \
 
257
     (void) (DESTRUCTOR),              \
 
258
     0)
 
259
# define gl_tls_get(NAME) \
 
260
    (NAME).singlethread_value
 
261
# define glthread_tls_set(KEY, POINTER) \
 
262
    ((KEY)->singlethread_value = (POINTER), 0)
 
263
# define glthread_tls_key_destroy(KEY) \
 
264
    0
 
265
 
 
266
#endif
 
267
 
 
268
/* ========================================================================= */
 
269
 
 
270
/* Macros with built-in error handling.  */
 
271
 
 
272
/* ------------------------- gl_tls_key_t datatype ------------------------- */
 
273
 
 
274
#define gl_tls_key_init(NAME, DESTRUCTOR) \
 
275
   do                                                 \
 
276
     {                                                \
 
277
       if (glthread_tls_key_init (&NAME, DESTRUCTOR)) \
 
278
         abort ();                                    \
 
279
     }                                                \
 
280
   while (0)
 
281
#define gl_tls_set(NAME, POINTER) \
 
282
   do                                         \
 
283
     {                                        \
 
284
       if (glthread_tls_set (&NAME, POINTER)) \
 
285
         abort ();                            \
 
286
     }                                        \
 
287
   while (0)
 
288
#define gl_tls_key_destroy(NAME) \
 
289
   do                                        \
 
290
     {                                       \
 
291
       if (glthread_tls_key_destroy (&NAME)) \
 
292
         abort ();                           \
 
293
     }                                       \
 
294
   while (0)
 
295
 
 
296
/* ========================================================================= */
 
297
 
 
298
#endif /* _TLS_H */