* Text.cpp (dissolveInset):
[lyx.git] / intl / lock.h
blob04d1369223096bee056c534e980347b1eed7e5e7
1 /* Locking in multithreaded situations.
2 Copyright (C) 2005-2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published
6 by the Free Software Foundation; either version 2, or (at your option)
7 any later version.
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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 USA. */
19 /* Written by Bruno Haible <bruno@clisp.org>, 2005.
20 Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
21 gthr-win32.h. */
23 /* This file contains locking primitives for use with a given thread library.
24 It does not contain primitives for creating threads or for other
25 synchronization primitives.
27 Normal (non-recursive) locks:
28 Type: gl_lock_t
29 Declaration: gl_lock_define(extern, name)
30 Initializer: gl_lock_define_initialized(, name)
31 Initialization: gl_lock_init (name);
32 Taking the lock: gl_lock_lock (name);
33 Releasing the lock: gl_lock_unlock (name);
34 De-initialization: gl_lock_destroy (name);
36 Read-Write (non-recursive) locks:
37 Type: gl_rwlock_t
38 Declaration: gl_rwlock_define(extern, name)
39 Initializer: gl_rwlock_define_initialized(, name)
40 Initialization: gl_rwlock_init (name);
41 Taking the lock: gl_rwlock_rdlock (name);
42 gl_rwlock_wrlock (name);
43 Releasing the lock: gl_rwlock_unlock (name);
44 De-initialization: gl_rwlock_destroy (name);
46 Recursive locks:
47 Type: gl_recursive_lock_t
48 Declaration: gl_recursive_lock_define(extern, name)
49 Initializer: gl_recursive_lock_define_initialized(, name)
50 Initialization: gl_recursive_lock_init (name);
51 Taking the lock: gl_recursive_lock_lock (name);
52 Releasing the lock: gl_recursive_lock_unlock (name);
53 De-initialization: gl_recursive_lock_destroy (name);
55 Once-only execution:
56 Type: gl_once_t
57 Initializer: gl_once_define(extern, name)
58 Execution: gl_once (name, initfunction);
62 #ifndef _LOCK_H
63 #define _LOCK_H
65 /* ========================================================================= */
67 #if USE_POSIX_THREADS
69 /* Use the POSIX threads library. */
71 # include <pthread.h>
72 # include <stdlib.h>
74 # ifdef __cplusplus
75 extern "C" {
76 # endif
78 # if PTHREAD_IN_USE_DETECTION_HARD
80 /* The pthread_in_use() detection needs to be done at runtime. */
81 # define pthread_in_use() \
82 glthread_in_use ()
83 extern int glthread_in_use (void);
85 # endif
87 # if USE_POSIX_THREADS_WEAK
89 /* Use weak references to the POSIX threads library. */
91 /* Weak references avoid dragging in external libraries if the other parts
92 of the program don't use them. Here we use them, because we don't want
93 every program that uses libintl to depend on libpthread. This assumes
94 that libpthread would not be loaded after libintl; i.e. if libintl is
95 loaded first, by an executable that does not depend on libpthread, and
96 then a module is dynamically loaded that depends on libpthread, libintl
97 will not be multithread-safe. */
99 /* The way to test at runtime whether libpthread is present is to test
100 whether a function pointer's value, such as &pthread_mutex_init, is
101 non-NULL. However, some versions of GCC have a bug through which, in
102 PIC mode, &foo != NULL always evaluates to true if there is a direct
103 call to foo(...) in the same function. To avoid this, we test the
104 address of a function in libpthread that we don't use. */
106 # pragma weak pthread_mutex_init
107 # pragma weak pthread_mutex_lock
108 # pragma weak pthread_mutex_unlock
109 # pragma weak pthread_mutex_destroy
110 # pragma weak pthread_rwlock_init
111 # pragma weak pthread_rwlock_rdlock
112 # pragma weak pthread_rwlock_wrlock
113 # pragma weak pthread_rwlock_unlock
114 # pragma weak pthread_rwlock_destroy
115 # pragma weak pthread_once
116 # pragma weak pthread_cond_init
117 # pragma weak pthread_cond_wait
118 # pragma weak pthread_cond_signal
119 # pragma weak pthread_cond_broadcast
120 # pragma weak pthread_cond_destroy
121 # pragma weak pthread_mutexattr_init
122 # pragma weak pthread_mutexattr_settype
123 # pragma weak pthread_mutexattr_destroy
124 # ifndef pthread_self
125 # pragma weak pthread_self
126 # endif
128 # if !PTHREAD_IN_USE_DETECTION_HARD
129 # pragma weak pthread_cancel
130 # define pthread_in_use() (pthread_cancel != NULL)
131 # endif
133 # else
135 # if !PTHREAD_IN_USE_DETECTION_HARD
136 # define pthread_in_use() 1
137 # endif
139 # endif
141 /* -------------------------- gl_lock_t datatype -------------------------- */
143 typedef pthread_mutex_t gl_lock_t;
144 # define gl_lock_define(STORAGECLASS, NAME) \
145 STORAGECLASS pthread_mutex_t NAME;
146 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
147 STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
148 # define gl_lock_initializer \
149 PTHREAD_MUTEX_INITIALIZER
150 # define gl_lock_init(NAME) \
151 if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
152 # define gl_lock_lock(NAME) \
153 if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
154 # define gl_lock_unlock(NAME) \
155 if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
156 # define gl_lock_destroy(NAME) \
157 if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
159 /* ------------------------- gl_rwlock_t datatype ------------------------- */
161 # if HAVE_PTHREAD_RWLOCK
163 # ifdef PTHREAD_RWLOCK_INITIALIZER
165 typedef pthread_rwlock_t gl_rwlock_t;
166 # define gl_rwlock_define(STORAGECLASS, NAME) \
167 STORAGECLASS pthread_rwlock_t NAME;
168 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
169 STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
170 # define gl_rwlock_initializer \
171 PTHREAD_RWLOCK_INITIALIZER
172 # define gl_rwlock_init(NAME) \
173 if (pthread_in_use () && pthread_rwlock_init (&NAME, NULL) != 0) abort ()
174 # define gl_rwlock_rdlock(NAME) \
175 if (pthread_in_use () && pthread_rwlock_rdlock (&NAME) != 0) abort ()
176 # define gl_rwlock_wrlock(NAME) \
177 if (pthread_in_use () && pthread_rwlock_wrlock (&NAME) != 0) abort ()
178 # define gl_rwlock_unlock(NAME) \
179 if (pthread_in_use () && pthread_rwlock_unlock (&NAME) != 0) abort ()
180 # define gl_rwlock_destroy(NAME) \
181 if (pthread_in_use () && pthread_rwlock_destroy (&NAME) != 0) abort ()
183 # else
185 typedef struct
187 int initialized;
188 pthread_mutex_t guard; /* protects the initialization */
189 pthread_rwlock_t rwlock; /* read-write lock */
191 gl_rwlock_t;
192 # define gl_rwlock_define(STORAGECLASS, NAME) \
193 STORAGECLASS gl_rwlock_t NAME;
194 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
195 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
196 # define gl_rwlock_initializer \
197 { 0, PTHREAD_MUTEX_INITIALIZER }
198 # define gl_rwlock_init(NAME) \
199 if (pthread_in_use ()) glthread_rwlock_init (&NAME)
200 # define gl_rwlock_rdlock(NAME) \
201 if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
202 # define gl_rwlock_wrlock(NAME) \
203 if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
204 # define gl_rwlock_unlock(NAME) \
205 if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
206 # define gl_rwlock_destroy(NAME) \
207 if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
208 extern void glthread_rwlock_init (gl_rwlock_t *lock);
209 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
210 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
211 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
212 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
214 # endif
216 # else
218 typedef struct
220 pthread_mutex_t lock; /* protects the remaining fields */
221 pthread_cond_t waiting_readers; /* waiting readers */
222 pthread_cond_t waiting_writers; /* waiting writers */
223 unsigned int waiting_writers_count; /* number of waiting writers */
224 int runcount; /* number of readers running, or -1 when a writer runs */
226 gl_rwlock_t;
227 # define gl_rwlock_define(STORAGECLASS, NAME) \
228 STORAGECLASS gl_rwlock_t NAME;
229 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
230 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
231 # define gl_rwlock_initializer \
232 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
233 # define gl_rwlock_init(NAME) \
234 if (pthread_in_use ()) glthread_rwlock_init (&NAME)
235 # define gl_rwlock_rdlock(NAME) \
236 if (pthread_in_use ()) glthread_rwlock_rdlock (&NAME)
237 # define gl_rwlock_wrlock(NAME) \
238 if (pthread_in_use ()) glthread_rwlock_wrlock (&NAME)
239 # define gl_rwlock_unlock(NAME) \
240 if (pthread_in_use ()) glthread_rwlock_unlock (&NAME)
241 # define gl_rwlock_destroy(NAME) \
242 if (pthread_in_use ()) glthread_rwlock_destroy (&NAME)
243 extern void glthread_rwlock_init (gl_rwlock_t *lock);
244 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
245 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
246 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
247 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
249 # endif
251 /* --------------------- gl_recursive_lock_t datatype --------------------- */
253 # if HAVE_PTHREAD_MUTEX_RECURSIVE
255 # if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
257 typedef pthread_mutex_t gl_recursive_lock_t;
258 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
259 STORAGECLASS pthread_mutex_t NAME;
260 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
261 STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
262 # ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
263 # define gl_recursive_lock_initializer \
264 PTHREAD_RECURSIVE_MUTEX_INITIALIZER
265 # else
266 # define gl_recursive_lock_initializer \
267 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
268 # endif
269 # define gl_recursive_lock_init(NAME) \
270 if (pthread_in_use () && pthread_mutex_init (&NAME, NULL) != 0) abort ()
271 # define gl_recursive_lock_lock(NAME) \
272 if (pthread_in_use () && pthread_mutex_lock (&NAME) != 0) abort ()
273 # define gl_recursive_lock_unlock(NAME) \
274 if (pthread_in_use () && pthread_mutex_unlock (&NAME) != 0) abort ()
275 # define gl_recursive_lock_destroy(NAME) \
276 if (pthread_in_use () && pthread_mutex_destroy (&NAME) != 0) abort ()
278 # else
280 typedef struct
282 pthread_mutex_t recmutex; /* recursive mutex */
283 pthread_mutex_t guard; /* protects the initialization */
284 int initialized;
286 gl_recursive_lock_t;
287 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
288 STORAGECLASS gl_recursive_lock_t NAME;
289 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
290 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
291 # define gl_recursive_lock_initializer \
292 { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
293 # define gl_recursive_lock_init(NAME) \
294 if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
295 # define gl_recursive_lock_lock(NAME) \
296 if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
297 # define gl_recursive_lock_unlock(NAME) \
298 if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
299 # define gl_recursive_lock_destroy(NAME) \
300 if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
301 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
302 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
303 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
304 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
306 # endif
308 # else
310 /* Old versions of POSIX threads on Solaris did not have recursive locks.
311 We have to implement them ourselves. */
313 typedef struct
315 pthread_mutex_t mutex;
316 pthread_t owner;
317 unsigned long depth;
319 gl_recursive_lock_t;
320 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
321 STORAGECLASS gl_recursive_lock_t NAME;
322 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
323 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
324 # define gl_recursive_lock_initializer \
325 { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
326 # define gl_recursive_lock_init(NAME) \
327 if (pthread_in_use ()) glthread_recursive_lock_init (&NAME)
328 # define gl_recursive_lock_lock(NAME) \
329 if (pthread_in_use ()) glthread_recursive_lock_lock (&NAME)
330 # define gl_recursive_lock_unlock(NAME) \
331 if (pthread_in_use ()) glthread_recursive_lock_unlock (&NAME)
332 # define gl_recursive_lock_destroy(NAME) \
333 if (pthread_in_use ()) glthread_recursive_lock_destroy (&NAME)
334 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
335 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
336 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
337 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
339 # endif
341 /* -------------------------- gl_once_t datatype -------------------------- */
343 typedef pthread_once_t gl_once_t;
344 # define gl_once_define(STORAGECLASS, NAME) \
345 STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
346 # define gl_once(NAME, INITFUNCTION) \
347 do \
349 if (pthread_in_use ()) \
351 if (pthread_once (&NAME, INITFUNCTION) != 0) \
352 abort (); \
354 else \
356 if (glthread_once_singlethreaded (&NAME)) \
357 INITFUNCTION (); \
360 while (0)
361 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
363 # ifdef __cplusplus
365 # endif
367 #endif
369 /* ========================================================================= */
371 #if USE_PTH_THREADS
373 /* Use the GNU Pth threads library. */
375 # include <pth.h>
376 # include <stdlib.h>
378 # ifdef __cplusplus
379 extern "C" {
380 # endif
382 # if USE_PTH_THREADS_WEAK
384 /* Use weak references to the GNU Pth threads library. */
386 # pragma weak pth_mutex_init
387 # pragma weak pth_mutex_acquire
388 # pragma weak pth_mutex_release
389 # pragma weak pth_rwlock_init
390 # pragma weak pth_rwlock_acquire
391 # pragma weak pth_rwlock_release
392 # pragma weak pth_once
394 # pragma weak pth_cancel
395 # define pth_in_use() (pth_cancel != NULL)
397 # else
399 # define pth_in_use() 1
401 # endif
403 /* -------------------------- gl_lock_t datatype -------------------------- */
405 typedef pth_mutex_t gl_lock_t;
406 # define gl_lock_define(STORAGECLASS, NAME) \
407 STORAGECLASS pth_mutex_t NAME;
408 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
409 STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
410 # define gl_lock_initializer \
411 PTH_MUTEX_INIT
412 # define gl_lock_init(NAME) \
413 if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
414 # define gl_lock_lock(NAME) \
415 if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
416 # define gl_lock_unlock(NAME) \
417 if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
418 # define gl_lock_destroy(NAME) \
419 (void)(&NAME)
421 /* ------------------------- gl_rwlock_t datatype ------------------------- */
423 typedef pth_rwlock_t gl_rwlock_t;
424 # define gl_rwlock_define(STORAGECLASS, NAME) \
425 STORAGECLASS pth_rwlock_t NAME;
426 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
427 STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
428 # define gl_rwlock_initializer \
429 PTH_RWLOCK_INIT
430 # define gl_rwlock_init(NAME) \
431 if (pth_in_use() && !pth_rwlock_init (&NAME)) abort ()
432 # define gl_rwlock_rdlock(NAME) \
433 if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RD, 0, NULL)) abort ()
434 # define gl_rwlock_wrlock(NAME) \
435 if (pth_in_use() && !pth_rwlock_acquire (&NAME, PTH_RWLOCK_RW, 0, NULL)) abort ()
436 # define gl_rwlock_unlock(NAME) \
437 if (pth_in_use() && !pth_rwlock_release (&NAME)) abort ()
438 # define gl_rwlock_destroy(NAME) \
439 (void)(&NAME)
441 /* --------------------- gl_recursive_lock_t datatype --------------------- */
443 /* In Pth, mutexes are recursive by default. */
444 typedef pth_mutex_t gl_recursive_lock_t;
445 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
446 STORAGECLASS pth_mutex_t NAME;
447 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
448 STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
449 # define gl_recursive_lock_initializer \
450 PTH_MUTEX_INIT
451 # define gl_recursive_lock_init(NAME) \
452 if (pth_in_use() && !pth_mutex_init (&NAME)) abort ()
453 # define gl_recursive_lock_lock(NAME) \
454 if (pth_in_use() && !pth_mutex_acquire (&NAME, 0, NULL)) abort ()
455 # define gl_recursive_lock_unlock(NAME) \
456 if (pth_in_use() && !pth_mutex_release (&NAME)) abort ()
457 # define gl_recursive_lock_destroy(NAME) \
458 (void)(&NAME)
460 /* -------------------------- gl_once_t datatype -------------------------- */
462 typedef pth_once_t gl_once_t;
463 # define gl_once_define(STORAGECLASS, NAME) \
464 STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
465 # define gl_once(NAME, INITFUNCTION) \
466 do \
468 if (pth_in_use ()) \
470 void (*gl_once_temp) (void) = INITFUNCTION; \
471 if (!pth_once (&NAME, glthread_once_call, &gl_once_temp)) \
472 abort (); \
474 else \
476 if (glthread_once_singlethreaded (&NAME)) \
477 INITFUNCTION (); \
480 while (0)
481 extern void glthread_once_call (void *arg);
482 extern int glthread_once_singlethreaded (pth_once_t *once_control);
484 # ifdef __cplusplus
486 # endif
488 #endif
490 /* ========================================================================= */
492 #if USE_SOLARIS_THREADS
494 /* Use the old Solaris threads library. */
496 # include <thread.h>
497 # include <synch.h>
498 # include <stdlib.h>
500 # ifdef __cplusplus
501 extern "C" {
502 # endif
504 # if USE_SOLARIS_THREADS_WEAK
506 /* Use weak references to the old Solaris threads library. */
508 # pragma weak mutex_init
509 # pragma weak mutex_lock
510 # pragma weak mutex_unlock
511 # pragma weak mutex_destroy
512 # pragma weak rwlock_init
513 # pragma weak rw_rdlock
514 # pragma weak rw_wrlock
515 # pragma weak rw_unlock
516 # pragma weak rwlock_destroy
517 # pragma weak thr_self
519 # pragma weak thr_suspend
520 # define thread_in_use() (thr_suspend != NULL)
522 # else
524 # define thread_in_use() 1
526 # endif
528 /* -------------------------- gl_lock_t datatype -------------------------- */
530 typedef mutex_t gl_lock_t;
531 # define gl_lock_define(STORAGECLASS, NAME) \
532 STORAGECLASS mutex_t NAME;
533 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
534 STORAGECLASS mutex_t NAME = gl_lock_initializer;
535 # define gl_lock_initializer \
536 DEFAULTMUTEX
537 # define gl_lock_init(NAME) \
538 if (thread_in_use () && mutex_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
539 # define gl_lock_lock(NAME) \
540 if (thread_in_use () && mutex_lock (&NAME) != 0) abort ()
541 # define gl_lock_unlock(NAME) \
542 if (thread_in_use () && mutex_unlock (&NAME) != 0) abort ()
543 # define gl_lock_destroy(NAME) \
544 if (thread_in_use () && mutex_destroy (&NAME) != 0) abort ()
546 /* ------------------------- gl_rwlock_t datatype ------------------------- */
548 typedef rwlock_t gl_rwlock_t;
549 # define gl_rwlock_define(STORAGECLASS, NAME) \
550 STORAGECLASS rwlock_t NAME;
551 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
552 STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
553 # define gl_rwlock_initializer \
554 DEFAULTRWLOCK
555 # define gl_rwlock_init(NAME) \
556 if (thread_in_use () && rwlock_init (&NAME, USYNC_THREAD, NULL) != 0) abort ()
557 # define gl_rwlock_rdlock(NAME) \
558 if (thread_in_use () && rw_rdlock (&NAME) != 0) abort ()
559 # define gl_rwlock_wrlock(NAME) \
560 if (thread_in_use () && rw_wrlock (&NAME) != 0) abort ()
561 # define gl_rwlock_unlock(NAME) \
562 if (thread_in_use () && rw_unlock (&NAME) != 0) abort ()
563 # define gl_rwlock_destroy(NAME) \
564 if (thread_in_use () && rwlock_destroy (&NAME) != 0) abort ()
566 /* --------------------- gl_recursive_lock_t datatype --------------------- */
568 /* Old Solaris threads did not have recursive locks.
569 We have to implement them ourselves. */
571 typedef struct
573 mutex_t mutex;
574 thread_t owner;
575 unsigned long depth;
577 gl_recursive_lock_t;
578 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
579 STORAGECLASS gl_recursive_lock_t NAME;
580 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
581 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
582 # define gl_recursive_lock_initializer \
583 { DEFAULTMUTEX, (thread_t) 0, 0 }
584 # define gl_recursive_lock_init(NAME) \
585 if (thread_in_use ()) glthread_recursive_lock_init (&NAME)
586 # define gl_recursive_lock_lock(NAME) \
587 if (thread_in_use ()) glthread_recursive_lock_lock (&NAME)
588 # define gl_recursive_lock_unlock(NAME) \
589 if (thread_in_use ()) glthread_recursive_lock_unlock (&NAME)
590 # define gl_recursive_lock_destroy(NAME) \
591 if (thread_in_use ()) glthread_recursive_lock_destroy (&NAME)
592 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
593 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
594 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
595 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
597 /* -------------------------- gl_once_t datatype -------------------------- */
599 typedef struct
601 volatile int inited;
602 mutex_t mutex;
604 gl_once_t;
605 # define gl_once_define(STORAGECLASS, NAME) \
606 STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
607 # define gl_once(NAME, INITFUNCTION) \
608 do \
610 if (thread_in_use ()) \
612 glthread_once (&NAME, INITFUNCTION); \
614 else \
616 if (glthread_once_singlethreaded (&NAME)) \
617 INITFUNCTION (); \
620 while (0)
621 extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
622 extern int glthread_once_singlethreaded (gl_once_t *once_control);
624 # ifdef __cplusplus
626 # endif
628 #endif
630 /* ========================================================================= */
632 #if USE_WIN32_THREADS
634 # include <windows.h>
636 # ifdef __cplusplus
637 extern "C" {
638 # endif
640 /* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
641 Semaphore types, because
642 - we need only to synchronize inside a single process (address space),
643 not inter-process locking,
644 - we don't need to support trylock operations. (TryEnterCriticalSection
645 does not work on Windows 95/98/ME. Packages that need trylock usually
646 define their own mutex type.) */
648 /* There is no way to statically initialize a CRITICAL_SECTION. It needs
649 to be done lazily, once only. For this we need spinlocks. */
651 typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
653 /* -------------------------- gl_lock_t datatype -------------------------- */
655 typedef struct
657 gl_spinlock_t guard; /* protects the initialization */
658 CRITICAL_SECTION lock;
660 gl_lock_t;
661 # define gl_lock_define(STORAGECLASS, NAME) \
662 STORAGECLASS gl_lock_t NAME;
663 # define gl_lock_define_initialized(STORAGECLASS, NAME) \
664 STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
665 # define gl_lock_initializer \
666 { { 0, -1 } }
667 # define gl_lock_init(NAME) \
668 glthread_lock_init (&NAME)
669 # define gl_lock_lock(NAME) \
670 glthread_lock_lock (&NAME)
671 # define gl_lock_unlock(NAME) \
672 glthread_lock_unlock (&NAME)
673 # define gl_lock_destroy(NAME) \
674 glthread_lock_destroy (&NAME)
675 extern void glthread_lock_init (gl_lock_t *lock);
676 extern void glthread_lock_lock (gl_lock_t *lock);
677 extern void glthread_lock_unlock (gl_lock_t *lock);
678 extern void glthread_lock_destroy (gl_lock_t *lock);
680 /* ------------------------- gl_rwlock_t datatype ------------------------- */
682 /* It is impossible to implement read-write locks using plain locks, without
683 introducing an extra thread dedicated to managing read-write locks.
684 Therefore here we need to use the low-level Event type. */
686 typedef struct
688 HANDLE *array; /* array of waiting threads, each represented by an event */
689 unsigned int count; /* number of waiting threads */
690 unsigned int alloc; /* length of allocated array */
691 unsigned int offset; /* index of first waiting thread in array */
693 gl_waitqueue_t;
694 typedef struct
696 gl_spinlock_t guard; /* protects the initialization */
697 CRITICAL_SECTION lock; /* protects the remaining fields */
698 gl_waitqueue_t waiting_readers; /* waiting readers */
699 gl_waitqueue_t waiting_writers; /* waiting writers */
700 int runcount; /* number of readers running, or -1 when a writer runs */
702 gl_rwlock_t;
703 # define gl_rwlock_define(STORAGECLASS, NAME) \
704 STORAGECLASS gl_rwlock_t NAME;
705 # define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
706 STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
707 # define gl_rwlock_initializer \
708 { { 0, -1 } }
709 # define gl_rwlock_init(NAME) \
710 glthread_rwlock_init (&NAME)
711 # define gl_rwlock_rdlock(NAME) \
712 glthread_rwlock_rdlock (&NAME)
713 # define gl_rwlock_wrlock(NAME) \
714 glthread_rwlock_wrlock (&NAME)
715 # define gl_rwlock_unlock(NAME) \
716 glthread_rwlock_unlock (&NAME)
717 # define gl_rwlock_destroy(NAME) \
718 glthread_rwlock_destroy (&NAME)
719 extern void glthread_rwlock_init (gl_rwlock_t *lock);
720 extern void glthread_rwlock_rdlock (gl_rwlock_t *lock);
721 extern void glthread_rwlock_wrlock (gl_rwlock_t *lock);
722 extern void glthread_rwlock_unlock (gl_rwlock_t *lock);
723 extern void glthread_rwlock_destroy (gl_rwlock_t *lock);
725 /* --------------------- gl_recursive_lock_t datatype --------------------- */
727 /* The Win32 documentation says that CRITICAL_SECTION already implements a
728 recursive lock. But we need not rely on it: It's easy to implement a
729 recursive lock without this assumption. */
731 typedef struct
733 gl_spinlock_t guard; /* protects the initialization */
734 DWORD owner;
735 unsigned long depth;
736 CRITICAL_SECTION lock;
738 gl_recursive_lock_t;
739 # define gl_recursive_lock_define(STORAGECLASS, NAME) \
740 STORAGECLASS gl_recursive_lock_t NAME;
741 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
742 STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
743 # define gl_recursive_lock_initializer \
744 { { 0, -1 }, 0, 0 }
745 # define gl_recursive_lock_init(NAME) \
746 glthread_recursive_lock_init (&NAME)
747 # define gl_recursive_lock_lock(NAME) \
748 glthread_recursive_lock_lock (&NAME)
749 # define gl_recursive_lock_unlock(NAME) \
750 glthread_recursive_lock_unlock (&NAME)
751 # define gl_recursive_lock_destroy(NAME) \
752 glthread_recursive_lock_destroy (&NAME)
753 extern void glthread_recursive_lock_init (gl_recursive_lock_t *lock);
754 extern void glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
755 extern void glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
756 extern void glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
758 /* -------------------------- gl_once_t datatype -------------------------- */
760 typedef struct
762 volatile int inited;
763 volatile long started;
764 CRITICAL_SECTION lock;
766 gl_once_t;
767 # define gl_once_define(STORAGECLASS, NAME) \
768 STORAGECLASS gl_once_t NAME = { -1, -1 };
769 # define gl_once(NAME, INITFUNCTION) \
770 glthread_once (&NAME, INITFUNCTION)
771 extern void glthread_once (gl_once_t *once_control, void (*initfunction) (void));
773 # ifdef __cplusplus
775 # endif
777 #endif
779 /* ========================================================================= */
781 #if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
783 /* Provide dummy implementation if threads are not supported. */
785 /* -------------------------- gl_lock_t datatype -------------------------- */
787 typedef int gl_lock_t;
788 # define gl_lock_define(STORAGECLASS, NAME)
789 # define gl_lock_define_initialized(STORAGECLASS, NAME)
790 # define gl_lock_init(NAME)
791 # define gl_lock_lock(NAME)
792 # define gl_lock_unlock(NAME)
794 /* ------------------------- gl_rwlock_t datatype ------------------------- */
796 typedef int gl_rwlock_t;
797 # define gl_rwlock_define(STORAGECLASS, NAME)
798 # define gl_rwlock_define_initialized(STORAGECLASS, NAME)
799 # define gl_rwlock_init(NAME)
800 # define gl_rwlock_rdlock(NAME)
801 # define gl_rwlock_wrlock(NAME)
802 # define gl_rwlock_unlock(NAME)
804 /* --------------------- gl_recursive_lock_t datatype --------------------- */
806 typedef int gl_recursive_lock_t;
807 # define gl_recursive_lock_define(STORAGECLASS, NAME)
808 # define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
809 # define gl_recursive_lock_init(NAME)
810 # define gl_recursive_lock_lock(NAME)
811 # define gl_recursive_lock_unlock(NAME)
813 /* -------------------------- gl_once_t datatype -------------------------- */
815 typedef int gl_once_t;
816 # define gl_once_define(STORAGECLASS, NAME) \
817 STORAGECLASS gl_once_t NAME = 0;
818 # define gl_once(NAME, INITFUNCTION) \
819 do \
821 if (NAME == 0) \
823 NAME = ~ 0; \
824 INITFUNCTION (); \
827 while (0)
829 #endif
831 /* ========================================================================= */
833 #endif /* _LOCK_H */