Initial git import
[sxemacs] / src / semaphore.h
1 /* semaphore.h - declarations for multi-threaded code
2
3    Copyright (C) 2006 Sebastian Freundt
4
5 This file is part of SXEmacs
6
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20
21 /* Synched up with: Not in FSF. */
22
23 #ifndef INCLUDED_semaphore_h_
24 #define INCLUDED_semaphore_h_
25
26 #if defined(HAVE_THREADS)
27 #include <pthread.h>
28 \f
29 /* decouple ordinary pthread mtxes */
30 #define sxe_thread_t    pthread_t
31 #define sxe_mutex_t     pthread_mutex_t
32
33 typedef void*(*sxe_thread_f)(void*);
34
35 #define SXE_MUTEX_INIT(_mtx)    pthread_mutex_init(_mtx, NULL)
36 #define SXE_MUTEX_FINI(_mtx)    pthread_mutex_destroy(_mtx)
37 #define SXE_MUTEX_LOCK(_mtx)    pthread_mutex_lock(_mtx)
38 #define SXE_MUTEX_UNLOCK(_mtx)  pthread_mutex_unlock(_mtx)
39
40 #define WITH_SXE_MUTEX(_mtx, args...)   \
41         SXE_MUTEX_LOCK(_mtx);           \
42         args;                           \
43         SXE_MUTEX_UNLOCK(_mtx);
44
45 \f
46 #define SXE_MSEMAPH_MAX_CONDITIONS      4
47
48 typedef struct sxe_semaphore_s *sxe_semaphore_t;
49 typedef struct sxe_msemaphore_s *sxe_msemaphore_t;
50 typedef struct sxe_refcounter_s *sxe_refcounter_t;
51
52 struct sxe_semaphore_s {
53         pthread_mutex_t mtx;
54         pthread_cond_t cnd;
55 };
56
57 struct sxe_msemaphore_s {
58         pthread_mutex_t mtx;
59         pthread_cond_t cnd[SXE_MSEMAPH_MAX_CONDITIONS];
60         int num_cnd;
61 };
62
63 /* a thread-safe reference counter */
64 struct sxe_refcounter_s {
65         pthread_mutex_t mtx;
66         int refcnt;
67 };
68
69 #define SXE_SEMAPH_MUTEX(_sem)          ((_sem)->mtx)
70 #define SXE_SEMAPH_COND(_sem)           ((_sem)->cnd)
71 #define SXE_MSEMAPH_MUTEX(_sem)         ((_sem)->mtx)
72 #define SXE_MSEMAPH_COND(_sem, _idx)    ((_sem)->cnd[(_idx)])
73
74 extern_inline void sxe_semaphore_init(sxe_semaphore_t);
75 extern_inline void sxe_msemaphore_init(sxe_msemaphore_t);
76 extern_inline void sxe_semaphore_finish(sxe_semaphore_t);
77 extern_inline void sxe_msemaphore_finish(sxe_msemaphore_t);
78 extern_inline void sxe_semaphore_trigger(sxe_semaphore_t);
79 extern_inline void sxe_msemaphore_trigger(sxe_msemaphore_t, int);
80 extern_inline void sxe_semaphore_trigger_all(sxe_semaphore_t);
81 extern_inline void sxe_msemaphore_trigger_all(sxe_msemaphore_t, int);
82 extern_inline void sxe_semaphore_synchronise(sxe_semaphore_t);
83 extern_inline void sxe_msemaphore_synchronise(sxe_msemaphore_t, int);
84
85 /* thread-safe refcounter */
86 extern_inline void sxe_refcounter_init(sxe_refcounter_t);
87 extern_inline void sxe_refcounter_finish(sxe_refcounter_t);
88 extern_inline sxe_refcounter_t sxe_refcounter_new(void);
89 extern_inline void sxe_refcounter_free(sxe_refcounter_t);
90 extern_inline int sxe_refcounter_value(sxe_refcounter_t);
91 extern_inline int sxe_refcounter_incref(sxe_refcounter_t);
92 extern_inline int sxe_refcounter_decref(sxe_refcounter_t);
93
94 \f
95 extern_inline void
96 sxe_semaphore_init(sxe_semaphore_t sem)
97 {
98         pthread_mutex_init(&(sem->mtx), NULL);
99         pthread_cond_init(&(sem->cnd), NULL);
100 }
101 extern_inline void
102 sxe_msemaphore_init(sxe_msemaphore_t sem)
103 {
104         int i;
105         pthread_mutex_init(&(sem->mtx), NULL);
106         for (i = 0; i < SXE_MSEMAPH_MAX_CONDITIONS; i++)
107                 pthread_cond_init(&(sem->cnd[i]), NULL);
108 }
109 extern_inline void
110 sxe_semaphore_finish(sxe_semaphore_t sem)
111 {
112         pthread_mutex_lock(&(sem->mtx));
113         pthread_mutex_unlock(&(sem->mtx));
114         pthread_cond_destroy(&(sem->cnd));
115         pthread_mutex_destroy(&(sem->mtx));
116 }
117 extern_inline void
118 sxe_msemaphore_finish(sxe_msemaphore_t sem)
119 {
120         int i;
121         pthread_mutex_lock(&(sem->mtx));
122         pthread_mutex_unlock(&(sem->mtx));
123         for (i = 0; i < SXE_MSEMAPH_MAX_CONDITIONS; i++)
124                 pthread_cond_destroy(&(sem->cnd[i]));
125         pthread_mutex_destroy(&(sem->mtx));
126 }
127
128 extern_inline void
129 sxe_semaphore_trigger(sxe_semaphore_t sem)
130 {
131         pthread_mutex_lock(&(sem->mtx));
132         pthread_cond_signal(&(sem->cnd));
133         pthread_mutex_unlock(&(sem->mtx));
134 }
135 extern_inline void
136 sxe_msemaphore_trigger(sxe_msemaphore_t sem, int idx)
137 {
138         pthread_mutex_lock(&(sem->mtx));
139         pthread_cond_signal(&(sem->cnd[idx]));
140         pthread_mutex_unlock(&(sem->mtx));
141 }
142
143 extern_inline void
144 sxe_semaphore_trigger_all(sxe_semaphore_t sem)
145 {
146         pthread_mutex_lock(&(sem->mtx));
147         pthread_cond_broadcast(&(sem->cnd));
148         pthread_mutex_unlock(&(sem->mtx));
149 }
150 extern_inline void
151 sxe_msemaphore_trigger_all(sxe_msemaphore_t sem, int idx)
152 {
153         pthread_mutex_lock(&(sem->mtx));
154         pthread_cond_broadcast(&(sem->cnd[idx]));
155         pthread_mutex_unlock(&(sem->mtx));
156 }
157
158 extern_inline void
159 sxe_semaphore_synchronise(sxe_semaphore_t sem)
160 {
161         pthread_mutex_lock(&(sem->mtx));
162         pthread_cond_wait(&(sem->cnd), &(sem->mtx));
163         pthread_mutex_unlock(&(sem->mtx));
164 }
165 extern_inline void
166 sxe_msemaphore_synchronise(sxe_msemaphore_t sem, int idx)
167 {
168         pthread_mutex_lock(&(sem->mtx));
169         pthread_cond_wait(&(sem->cnd[idx]), &(sem->mtx));
170         pthread_mutex_unlock(&(sem->mtx));
171 }
172
173 #define SXE_SEMAPH_INIT(_sem)   sxe_semaphore_init(_sem)
174 #define SXE_MSEMAPH_INIT(_sem)  sxe_msemaphore_init(_sem)
175 #define SXE_SEMAPH_FINI(_sem)   sxe_semaphore_finish(_sem)
176 #define SXE_MSEMAPH_FINI(_sem)  sxe_msemaphore_finish(_sem)
177
178 #define SXE_SEMAPH_LOCK(_sem)                           \
179         pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem));
180
181 #define SXE_SEMAPH_UNLOCK(_sem)                         \
182         pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem));
183
184 #define SXE_SEMAPH_SIGNAL(_sem)                         \
185         pthread_cond_signal(&SXE_SEMAPH_COND(_sem));
186
187 #define SXE_SEMAPH_BROADCAST(_sem)                      \
188         pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem));
189
190 #define SXE_SEMAPH_WAIT(_sem)                   \
191         pthread_cond_wait(&SXE_SEMAPH_COND(_sem), &SXE_SEMAPH_MUTEX(_sem));
192
193 #define SXE_MSEMAPH_LOCK(_sem)                          \
194         pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem));
195
196 #define SXE_MSEMAPH_UNLOCK(_sem)                                \
197         pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem));
198
199 #define SXE_MSEMAPH_SIGNAL(_sem, _idx)                          \
200         pthread_cond_signal(&SXE_MSEMAPH_COND(_sem, _idx));
201
202 #define SXE_MSEMAPH_BROADCAST(_sem, _idx)                       \
203         pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem, _idx));
204
205 #define SXE_MSEMAPH_WAIT(_sem, _idx)                                    \
206         pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx),                \
207                           &SXE_MSEMAPH_MUTEX(_sem));
208
209 #define SXE_SEMAPH_TRIGGER(_sem)        sxe_semaphore_trigger(_sem)
210 #define SXE_MSEMAPH_TRIGGER(_sem, _idx) sxe_msemaphore_trigger(_sem, _idx)
211 #define SXE_SEMAPH_TRIGGER_ALL(_sem)    sxe_semaphore_trigger_all(_sem)
212 #define SXE_MSEMAPH_TRIGGER_ALL(_sem, _idx)     \
213         sxe_msemaphore_trigger_all(_sem, _idx)
214 #define SXE_SEMAPH_SYNCH(_sem)          sxe_semaphore_synchronise(_sem);
215 #define SXE_MSEMAPH_SYNCH(_sem, _idx)   sxe_msemaphore_synchronise(_sem, _idx);
216
217 #define WITH_SXE_SEMAPH_SYNCH(_sem, args...)                    \
218 do {                                                            \
219         pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem));            \
220         args;                                                   \
221         pthread_cond_wait(&SXE_SEMAPH_COND(_sem),               \
222                           &SXE_SEMAPH_MUTEX(_sem));             \
223         pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem));          \
224 } while (0)
225
226 #define WITH_SXE_MSEMAPH_SYNCH(_sem, _idx, args...)             \
227 do {                                                            \
228         pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem));           \
229         args;                                                   \
230         pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx),        \
231                           &SXE_MSEMAPH_MUTEX(_sem));            \
232         pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem));         \
233 } while (0)
234
235
236 /* thread-safe refcounter */
237 extern_inline void
238 sxe_refcounter_init(sxe_refcounter_t rc)
239 {
240         pthread_mutex_init(&(rc->mtx), NULL);
241         rc->refcnt = 0;
242 }
243 extern_inline void
244 sxe_refcounter_finish(sxe_refcounter_t rc)
245 {
246         pthread_mutex_lock(&(rc->mtx));
247         pthread_mutex_unlock(&(rc->mtx));
248         pthread_mutex_destroy(&(rc->mtx));
249         rc->refcnt = 0;
250 }
251 extern_inline sxe_refcounter_t
252 sxe_refcounter_new(void)
253 {
254         sxe_refcounter_t rc = xnew(struct sxe_refcounter_s);
255         sxe_refcounter_init(rc);
256         return rc;
257 }
258 extern_inline void
259 sxe_refcounter_free(sxe_refcounter_t rc)
260 {
261         sxe_refcounter_finish(rc);
262         xfree(rc);
263         return;
264 }
265 /* accessors */
266 extern_inline int
267 sxe_refcounter_value(sxe_refcounter_t rc)
268 {
269         int result;
270
271         pthread_mutex_lock(&(rc->mtx));
272         result = rc->refcnt;
273         pthread_mutex_unlock(&(rc->mtx));
274
275         return result;
276 }
277 extern_inline int
278 sxe_refcounter_incref(sxe_refcounter_t rc)
279 {
280         int result;
281
282         pthread_mutex_lock(&(rc->mtx));
283         result = ++rc->refcnt;
284         pthread_mutex_unlock(&(rc->mtx));
285
286         return result;
287 }
288 extern_inline int
289 sxe_refcounter_decref(sxe_refcounter_t rc)
290 {
291         int result;
292
293         pthread_mutex_lock(&(rc->mtx));
294         result = --rc->refcnt;
295         pthread_mutex_unlock(&(rc->mtx));
296
297         return result;
298 }
299
300 /* pthreads */
301 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
302 # define xthread_create         GC_pthread_create
303 # define xthread_join           GC_pthread_join
304 # define xthread_detach         GC_pthread_detach
305 #else  /* !BDWGC */
306 # define xthread_create         pthread_create
307 # define xthread_join           pthread_join
308 # define xthread_detach         pthread_detach
309 #endif  /* BDWGC */
310
311 #else  /* !HAVE_THREADS */
312
313 typedef void *sxe_semaphore_t;
314 #define sxe_mutex_t     void
315 #define sxe_thread_t    void
316
317 #define SXE_MUTEX_INIT(_mtx)
318 #define SXE_MUTEX_FINI(_mtx)
319 #define SXE_MUTEX_LOCK(_mtx)
320 #define SXE_MUTEX_UNLOCK(_mtx)
321
322 #endif
323 #endif  /* INCLUDED_semaphore_h */
324