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