Replaced deprecated gtk_menu_popup() calls with modern constructs in gtk3.22-client
[freeciv.git] / utility / fcthread.c
blobdff741f88db07e708fad3f13318a1288c5ac9248
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)
6 any later version.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* utility */
19 #include "log.h"
20 #include "mem.h"
21 #include "support.h"
23 #include "fcthread.h"
25 #ifdef FREECIV_HAVE_C11_THREADS
27 struct fc_thread_wrap_data {
28 void *arg;
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);
42 free(data);
44 return EXIT_SUCCESS;
47 /**********************************************************************
48 Create new thread
49 ***********************************************************************/
50 int fc_thread_start(fc_thread *thread, void (*function) (void *arg),
51 void *arg)
53 int ret;
55 /* Freed by child thread once it's finished with data */
56 struct fc_thread_wrap_data *data = fc_malloc(sizeof(*data));
58 data->arg = arg;
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 /**********************************************************************
77 Initialize mutex
78 ***********************************************************************/
79 void fc_init_mutex(fc_mutex *mutex)
81 mtx_init(mutex, mtx_plain|mtx_recursive);
84 /**********************************************************************
85 Destroy mutex
86 ***********************************************************************/
87 void fc_destroy_mutex(fc_mutex *mutex)
89 mtx_destroy(mutex);
92 /**********************************************************************
93 Lock mutex
94 ***********************************************************************/
95 void fc_allocate_mutex(fc_mutex *mutex)
97 mtx_lock(mutex);
100 /**********************************************************************
101 Release mutex
102 ***********************************************************************/
103 void fc_release_mutex(fc_mutex *mutex)
105 mtx_unlock(mutex);
108 /**********************************************************************
109 Initialize condition
110 ***********************************************************************/
111 void fc_thread_cond_init(fc_thread_cond *cond)
113 cnd_init(cond);
116 /**********************************************************************
117 Destroy condition
118 ***********************************************************************/
119 void fc_thread_cond_destroy(fc_thread_cond *cond)
121 cnd_destroy(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)
137 cnd_signal(cond);
140 #elif defined(FREECIV_HAVE_PTHREAD)
142 struct fc_thread_wrap_data {
143 void *arg;
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);
157 free(data);
159 return NULL;
162 /**********************************************************************
163 Create new thread
164 ***********************************************************************/
165 int fc_thread_start(fc_thread *thread, void (*function) (void *arg),
166 void *arg)
168 int ret;
169 pthread_attr_t attr;
171 /* Freed by child thread once it's finished with data */
172 struct fc_thread_wrap_data *data = fc_malloc(sizeof(*data));
174 data->arg = arg;
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);
186 return ret;
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 /**********************************************************************
200 Initialize mutex
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 /**********************************************************************
215 Destroy mutex
216 ***********************************************************************/
217 void fc_destroy_mutex(fc_mutex *mutex)
219 pthread_mutex_destroy(mutex);
222 /**********************************************************************
223 Lock mutex
224 ***********************************************************************/
225 void fc_allocate_mutex(fc_mutex *mutex)
227 pthread_mutex_lock(mutex);
230 /**********************************************************************
231 Release mutex
232 ***********************************************************************/
233 void fc_release_mutex(fc_mutex *mutex)
235 pthread_mutex_unlock(mutex);
238 /**********************************************************************
239 Initialize condition
240 ***********************************************************************/
241 void fc_thread_cond_init(fc_thread_cond *cond)
243 pthread_cond_init(cond, NULL);
246 /**********************************************************************
247 Destroy condition
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 {
273 void *arg;
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);
287 free(data);
289 return 0;
292 /**********************************************************************
293 Create new thread
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));
300 data->arg = arg;
301 data->func = function;
303 *thread = CreateThread(NULL, 0, &fc_thread_wrapper, data, 0, NULL);
305 if (*thread == NULL) {
306 return 1;
309 return 0;
312 /**********************************************************************
313 Wait for thread to finish
314 ***********************************************************************/
315 void fc_thread_wait(fc_thread *thread)
317 DWORD exit_code;
319 GetExitCodeThread(*thread, &exit_code);
321 while (exit_code == STILL_ACTIVE) {
322 fc_usleep(1000);
323 GetExitCodeThread(*thread, &exit_code);
326 CloseHandle(*thread);
329 /**********************************************************************
330 Initialize mutex
331 ***********************************************************************/
332 void fc_init_mutex(fc_mutex *mutex)
334 *mutex = CreateMutex(NULL, FALSE, NULL);
337 /**********************************************************************
338 Destroy mutex
339 ***********************************************************************/
340 void fc_destroy_mutex(fc_mutex *mutex)
342 CloseHandle(*mutex);
345 /**********************************************************************
346 Lock mutex
347 ***********************************************************************/
348 void fc_allocate_mutex(fc_mutex *mutex)
350 WaitForSingleObject(*mutex, INFINITE);
353 /**********************************************************************
354 Release mutex
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
408 return TRUE;
409 #else
410 return FALSE;
411 #endif