1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
15 #include <fc_config.h>
25 #ifdef FREECIV_HAVE_C11_THREADS
27 struct fc_thread_wrap_data
{
29 void (*func
)(void *arg
);
32 /**********************************************************************
33 Wrapper which fingerprint matches one required by pthread_create().
34 Calls function which matches fingerprint required by fc_thread_start()
35 ***********************************************************************/
36 static int fc_thread_wrapper(void *arg
)
38 struct fc_thread_wrap_data
*data
= (struct fc_thread_wrap_data
*) arg
;
40 data
->func(data
->arg
);
47 /**********************************************************************
49 ***********************************************************************/
50 int fc_thread_start(fc_thread
*thread
, void (*function
) (void *arg
),
55 /* Freed by child thread once it's finished with data */
56 struct fc_thread_wrap_data
*data
= fc_malloc(sizeof(*data
));
59 data
->func
= function
;
61 ret
= thrd_create(thread
, &fc_thread_wrapper
, data
);
63 return ret
!= thrd_success
;
66 /**********************************************************************
67 Wait for thread to finish
68 ***********************************************************************/
69 void fc_thread_wait(fc_thread
*thread
)
71 int *return_value
= NULL
;
73 thrd_join(*thread
, return_value
);
76 /**********************************************************************
78 ***********************************************************************/
79 void fc_init_mutex(fc_mutex
*mutex
)
81 mtx_init(mutex
, mtx_plain
|mtx_recursive
);
84 /**********************************************************************
86 ***********************************************************************/
87 void fc_destroy_mutex(fc_mutex
*mutex
)
92 /**********************************************************************
94 ***********************************************************************/
95 void fc_allocate_mutex(fc_mutex
*mutex
)
100 /**********************************************************************
102 ***********************************************************************/
103 void fc_release_mutex(fc_mutex
*mutex
)
108 /**********************************************************************
110 ***********************************************************************/
111 void fc_thread_cond_init(fc_thread_cond
*cond
)
116 /**********************************************************************
118 ***********************************************************************/
119 void fc_thread_cond_destroy(fc_thread_cond
*cond
)
124 /**********************************************************************
125 Wait for condition to be fulfilled
126 ***********************************************************************/
127 void fc_thread_cond_wait(fc_thread_cond
*cond
, fc_mutex
*mutex
)
129 cnd_wait(cond
, mutex
);
132 /**********************************************************************
133 Signal other thread to continue on fulfilled condition
134 ***********************************************************************/
135 void fc_thread_cond_signal(fc_thread_cond
*cond
)
140 #elif defined(FREECIV_HAVE_PTHREAD)
142 struct fc_thread_wrap_data
{
144 void (*func
)(void *arg
);
147 /**********************************************************************
148 Wrapper which fingerprint matches one required by pthread_create().
149 Calls function which matches fingerprint required by fc_thread_start()
150 ***********************************************************************/
151 static void *fc_thread_wrapper(void *arg
)
153 struct fc_thread_wrap_data
*data
= (struct fc_thread_wrap_data
*) arg
;
155 data
->func(data
->arg
);
162 /**********************************************************************
164 ***********************************************************************/
165 int fc_thread_start(fc_thread
*thread
, void (*function
) (void *arg
),
171 /* Freed by child thread once it's finished with data */
172 struct fc_thread_wrap_data
*data
= fc_malloc(sizeof(*data
));
175 data
->func
= function
;
177 /* Explicitly set thread as joinable to maximize portability
178 between pthread implementations */
179 pthread_attr_init(&attr
);
180 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_JOINABLE
);
182 ret
= pthread_create(thread
, &attr
, &fc_thread_wrapper
, data
);
184 pthread_attr_destroy(&attr
);
189 /**********************************************************************
190 Wait for thread to finish
191 ***********************************************************************/
192 void fc_thread_wait(fc_thread
*thread
)
194 void **return_value
= NULL
;
196 pthread_join(*thread
, return_value
);
199 /**********************************************************************
201 ***********************************************************************/
202 void fc_init_mutex(fc_mutex
*mutex
)
204 pthread_mutexattr_t attr
;
206 pthread_mutexattr_init(&attr
);
207 pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
);
209 pthread_mutex_init(mutex
, &attr
);
211 pthread_mutexattr_destroy(&attr
);
214 /**********************************************************************
216 ***********************************************************************/
217 void fc_destroy_mutex(fc_mutex
*mutex
)
219 pthread_mutex_destroy(mutex
);
222 /**********************************************************************
224 ***********************************************************************/
225 void fc_allocate_mutex(fc_mutex
*mutex
)
227 pthread_mutex_lock(mutex
);
230 /**********************************************************************
232 ***********************************************************************/
233 void fc_release_mutex(fc_mutex
*mutex
)
235 pthread_mutex_unlock(mutex
);
238 /**********************************************************************
240 ***********************************************************************/
241 void fc_thread_cond_init(fc_thread_cond
*cond
)
243 pthread_cond_init(cond
, NULL
);
246 /**********************************************************************
248 ***********************************************************************/
249 void fc_thread_cond_destroy(fc_thread_cond
*cond
)
251 pthread_cond_destroy(cond
);
254 /**********************************************************************
255 Wait for condition to be fulfilled
256 ***********************************************************************/
257 void fc_thread_cond_wait(fc_thread_cond
*cond
, fc_mutex
*mutex
)
259 pthread_cond_wait(cond
, mutex
);
262 /**********************************************************************
263 Signal other thread to continue on fulfilled condition
264 ***********************************************************************/
265 void fc_thread_cond_signal(fc_thread_cond
*cond
)
267 pthread_cond_signal(cond
);
270 #elif defined(FREECIV_HAVE_WINTHREADS)
272 struct fc_thread_wrap_data
{
274 void (*func
)(void *arg
);
277 /**********************************************************************
278 Wrapper which fingerprint matches one required by CreateThread().
279 Calls function which matches fingerprint required by fc_thread_start()
280 ***********************************************************************/
281 static DWORD WINAPI
fc_thread_wrapper(LPVOID arg
)
283 struct fc_thread_wrap_data
*data
= (struct fc_thread_wrap_data
*) arg
;
285 data
->func(data
->arg
);
292 /**********************************************************************
294 ***********************************************************************/
295 int fc_thread_start(fc_thread
*thread
, void (*function
) (void *arg
), void *arg
)
297 /* Freed by child thread once it's finished with data */
298 struct fc_thread_wrap_data
*data
= fc_malloc(sizeof(*data
));
301 data
->func
= function
;
303 *thread
= CreateThread(NULL
, 0, &fc_thread_wrapper
, data
, 0, NULL
);
305 if (*thread
== NULL
) {
312 /**********************************************************************
313 Wait for thread to finish
314 ***********************************************************************/
315 void fc_thread_wait(fc_thread
*thread
)
319 GetExitCodeThread(*thread
, &exit_code
);
321 while (exit_code
== STILL_ACTIVE
) {
323 GetExitCodeThread(*thread
, &exit_code
);
326 CloseHandle(*thread
);
329 /**********************************************************************
331 ***********************************************************************/
332 void fc_init_mutex(fc_mutex
*mutex
)
334 *mutex
= CreateMutex(NULL
, FALSE
, NULL
);
337 /**********************************************************************
339 ***********************************************************************/
340 void fc_destroy_mutex(fc_mutex
*mutex
)
345 /**********************************************************************
347 ***********************************************************************/
348 void fc_allocate_mutex(fc_mutex
*mutex
)
350 WaitForSingleObject(*mutex
, INFINITE
);
353 /**********************************************************************
355 ***********************************************************************/
356 void fc_release_mutex(fc_mutex
*mutex
)
358 ReleaseMutex(*mutex
);
361 /* TODO: Windows thread condition variable support.
362 * Currently related functions are always dummy ones below
363 * (see #ifndef FREECIV_HAVE_THREAD_COND) */
365 #else /* No thread implementation */
367 #error "No working thread implementation"
369 #endif /* FREECIV_HAVE_PTHREAD || FREECIV_HAVE_WINTHREADS */
372 #ifndef FREECIV_HAVE_THREAD_COND
374 /* Dummy thread condition variable functions */
376 /**********************************************************************
377 Dummy fc_thread_cond_init()
378 ***********************************************************************/
379 void fc_thread_cond_init(fc_thread_cond
*cond
)
382 /**********************************************************************
383 Dummy fc_thread_cond_destroy()
384 ***********************************************************************/
385 void fc_thread_cond_destroy(fc_thread_cond
*cond
)
388 /**********************************************************************
389 Dummy fc_thread_cond_wait()
390 ***********************************************************************/
391 void fc_thread_cond_wait(fc_thread_cond
*cond
, fc_mutex
*mutex
)
394 /**********************************************************************
395 Dummy fc_thread_cond_signal()
396 ***********************************************************************/
397 void fc_thread_cond_signal(fc_thread_cond
*cond
)
400 #endif /* !FREECIV_HAVE_THREAD_COND */
402 /**********************************************************************
403 Has freeciv thread condition variable implementation
404 ***********************************************************************/
405 bool has_thread_cond_impl(void)
407 #ifdef FREECIV_HAVE_THREAD_COND