C Standard Library Extensions 1.3.1
cxthread.h
1/*
2 * This file is part of the ESO C Extension Library
3 * Copyright (C) 2001-2026 European Southern Observatory
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
17 */
18
19#ifndef CXTHREAD_H_
20#define CXTHREAD_H_
21
22#if HAVE_CONFIG_H
23# include "config.h"
24#endif
25
26#ifdef HAVE_PTHREAD_H
27# include <pthread.h>
28#endif
29
30
31/*
32 * Map local types and functions to the POSIX thread model implementation
33 */
34
35#if defined(CX_THREADS_ENABLED)
36
37# if defined(HAVE_PTHREAD_H)
38
39# define CX_STATIC_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
40# define CX_STATIC_ONCE_INIT PTHREAD_ONCE_INIT
41
42# define CX_MUTEX_TYPE_DEFAULT PTHREAD_MUTEX_DEFAULT
43# define CX_MUTEX_TYPE_NORMAL PTHREAD_MUTEX_NORMAL
44# define CX_MUTEX_TYPE_RECURSIVE PTHREAD_MUTEX_RECURSIVE
45
46typedef pthread_mutex_t cx_mutex;
47typedef pthread_once_t cx_once;
48typedef pthread_key_t cx_private;
49
50# define cx_mutex_init(mutex, type) \
51 do { \
52 pthread_mutexattr_t attr; \
53 \
54 pthread_mutexattr_init(&attr); \
55 pthread_mutexattr_settype(&attr, (type)); \
56 \
57 pthread_mutex_init(mutex, &attr); \
58 \
59 pthread_mutexattr_destroy(&attr); \
60 } while (0)
61
62# define cx_mutex_lock(mutex) pthread_mutex_lock((mutex))
63# define cx_mutex_trylock(mutex) pthread_mutex_trylock((mutex))
64# define cx_mutex_unlock(mutex) pthread_mutex_unlock((mutex))
65
66# define cx_thread_once(name, func, args) pthread_once(&(name), (func))
67
68# define cx_private_init(name, func) pthread_key_create(&(name), (func))
69# define cx_private_set(name, data) pthread_setspecific((name), (data))
70# define cx_private_get(name) pthread_getspecific((name))
71
72# else /* !HAVE_PTHREAD_H */
73# error "Thread support is requested, but POSIX thread model is not present!"
74# endif /* !HAVE_PTHREAD_H */
75
76#else /* !CX_THREADS_ENABLED */
77
78typedef struct cx_private cx_private;
79
80# define cx_mutex_init(mutex, type) /* empty */
81
82# define cx_mutex_lock(mutex) /* empty */
83# define cx_mutex_trylock(mutex) /* empty */
84# define cx_mutex_unlock(mutex) /* empty */
85
86# define cx_thread_once(name, func, args) (func)()
87
88# define cx_private_init(name, func) /* empty */
89# define cx_private_set(name, data) ((name) = (data))
90# define cx_private_get(name) (name)
91
92#endif /* !CX_THREADS_ENABLED */
93
94
95/*
96 * Convenience macros to setup locks for global variables.
97 * These macros expand to nothing, if thread support was not enabled.
98 */
99
100#define CX_LOCK_NAME(name) _cx__##name##_lock
101
102#if defined(CX_THREADS_ENABLED)
103
104# define CX_LOCK_DEFINE_STATIC(name) static CX_LOCK_DEFINE(name)
105# define CX_LOCK_DEFINE(name) cx_mutex CX_LOCK_NAME(name)
106# define CX_LOCK_EXTERN(name) extern cx_mutex CX_LOCK_NAME(name)
107
108# define CX_LOCK_DEFINE_INITIALIZED_STATIC(name) \
109 static CX_LOCK_DEFINE_INITIALIZED(name)
110# define CX_LOCK_DEFINE_INITIALIZED(name) \
111 CX_LOCK_DEFINE(name) = CX_STATIC_MUTEX_INIT
112
113# define CX_INITLOCK(name, type) cx_mutex_init(&CX_LOCK_NAME(name), (type))
114
115# define CX_LOCK(name) cx_mutex_lock(&CX_LOCK_NAME(name))
116# define CX_TRYLOCK(name) cx_mutex_trylock(&CX_LOCK_NAME(name))
117# define CX_UNLOCK(name) cx_mutex_unlock(&CX_LOCK_NAME(name))
118
119#else /* !CX_THREADS_ENABLED */
120
121# define CX_LOCK_DEFINE_STATIC(name) /* empty */
122# define CX_LOCK_DEFINE(name) /* empty */
123# define CX_LOCK_EXTERN(name) /* empty */
124
125# define CX_LOCK_DEFINE_INITIALIZED_STATIC(name) /* empty */
126# define CX_LOCK_DEFINE_INITIALIZED(name) /* empty */
127
128# define CX_INITLOCK(name, type) /* empty */
129
130# define CX_LOCK(name) /* empty */
131# define CX_TRYLOCK(name) (TRUE)
132# define CX_UNLOCK(name) /* empty */
133
134#endif /* !CX_THREADS_ENABLED */
135
136
137/*
138 * Convenience macros for setting up mutexes for one time initalizations
139 */
140
141#if defined(CX_THREADS_ENABLED)
142
143# define CX_ONCE_DEFINE_STATIC(name) static CX_ONCE_DEFINE(name)
144# define CX_ONCE_DEFINE(name) cx_once(name)
145
146# define CX_ONCE_DEFINE_INITIALIZED_STATIC(name) \
147 static CX_ONCE_DEFINE_INITIALIZED(name)
148# define CX_ONCE_DEFINE_INITIALIZED(name) cx_once(name) = CX_STATIC_ONCE_INIT
149
150#else /* !CX_THREADS_ENABLED */
151
152# define CX_ONCE_DEFINE_STATIC(name) /* empty */
153# define CX_ONCE_DEFINE(name) /* empty */
154
155# define CX_ONCE_DEFINE_INITIALIZED_STATIC(name) /* empty */
156# define CX_ONCE_DEFINE_INITIALIZED(name) /* empty */
157
158#endif /* !CX_THREADS_ENABLED */
159
160
161/*
162 * Convenience macros for setting up thread-specific data
163 */
164
165#if defined(CX_THREADS_ENABLED)
166
167# define CX_PRIVATE_DEFINE_STATIC(name) cx_private(name)
168
169#else /* !CX_THREADS_ENABLED */
170
171# define CX_PRIVATE_DEFINE_STATIC(name) static cx_private *(name)
172
173#endif /* !CX_THREADS_ENABLED */
174
175#endif /* CXTHREAD_H_ */