Support changing players' science box in the editor.
[freeciv.git] / utility / fcthread.c
blobba859a0f0158834a0930d0ca312d279707ec3d29
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 HAVE_PTHREAD
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 void *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 NULL;
47 /**********************************************************************
48 Create new thread
49 ***********************************************************************/
50 int fc_thread_start(fc_thread *thread, void (*function) (void *arg),
51 void *arg)
53 int ret;
54 pthread_attr_t attr;
56 /* Freed by child thread once it's finished with data */
57 struct fc_thread_wrap_data *data = fc_malloc(sizeof(*data));
59 data->arg = arg;
60 data->func = function;
62 /* Explicitly set thread as joinable to maximize portability
63 between pthread implementations */
64 pthread_attr_init(&attr);
65 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
67 ret = pthread_create(thread, &attr, &fc_thread_wrapper, data);
69 pthread_attr_destroy(&attr);
71 return ret;
74 /**********************************************************************
75 Wait for thread to finish
76 ***********************************************************************/
77 void fc_thread_wait(fc_thread *thread)
79 void **return_value = NULL;
81 pthread_join(*thread, return_value);
84 /**********************************************************************
85 Initialize mutex
86 ***********************************************************************/
87 void fc_init_mutex(fc_mutex *mutex)
89 pthread_mutexattr_t attr;
91 pthread_mutexattr_init(&attr);
92 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
94 pthread_mutex_init(mutex, &attr);
96 pthread_mutexattr_destroy(&attr);
99 /**********************************************************************
100 Destroy mutex
101 ***********************************************************************/
102 void fc_destroy_mutex(fc_mutex *mutex)
104 pthread_mutex_destroy(mutex);
107 /**********************************************************************
108 Lock mutex
109 ***********************************************************************/
110 void fc_allocate_mutex(fc_mutex *mutex)
112 pthread_mutex_lock(mutex);
115 /**********************************************************************
116 Release mutex
117 ***********************************************************************/
118 void fc_release_mutex(fc_mutex *mutex)
120 pthread_mutex_unlock(mutex);
123 /**********************************************************************
124 Initialize condition
125 ***********************************************************************/
126 void fc_thread_cond_init(fc_thread_cond *cond)
128 pthread_cond_init(cond, NULL);
131 /**********************************************************************
132 Destroy condition
133 ***********************************************************************/
134 void fc_thread_cond_destroy(fc_thread_cond *cond)
136 pthread_cond_destroy(cond);
139 /**********************************************************************
140 Wait for condition to be fulfilled
141 ***********************************************************************/
142 void fc_thread_cond_wait(fc_thread_cond *cond, fc_mutex *mutex)
144 pthread_cond_wait(cond, mutex);
147 /**********************************************************************
148 Signal other thread to continue on fulfilled condition
149 ***********************************************************************/
150 void fc_thread_cond_signal(fc_thread_cond *cond)
152 pthread_cond_signal(cond);
155 #elif defined(HAVE_WINTHREADS)
157 struct fc_thread_wrap_data {
158 void *arg;
159 void (*func)(void *arg);
162 /**********************************************************************
163 Wrapper which fingerprint matches one required by CreateThread().
164 Calls function which matches fingerprint required by fc_thread_start()
165 ***********************************************************************/
166 static DWORD WINAPI fc_thread_wrapper(LPVOID arg)
168 struct fc_thread_wrap_data *data = (struct fc_thread_wrap_data *) arg;
170 data->func(data->arg);
172 free(data);
174 return 0;
177 /**********************************************************************
178 Create new thread
179 ***********************************************************************/
180 int fc_thread_start(fc_thread *thread, void (*function) (void *arg), void *arg)
182 /* Freed by child thread once it's finished with data */
183 struct fc_thread_wrap_data *data = fc_malloc(sizeof(*data));
185 data->arg = arg;
186 data->func = function;
188 *thread = CreateThread(NULL, 0, &fc_thread_wrapper, data, 0, NULL);
190 if (*thread == NULL) {
191 return 1;
194 return 0;
197 /**********************************************************************
198 Wait for thread to finish
199 ***********************************************************************/
200 void fc_thread_wait(fc_thread *thread)
202 DWORD exit_code;
204 GetExitCodeThread(*thread, &exit_code);
206 while (exit_code == STILL_ACTIVE) {
207 fc_usleep(1000);
208 GetExitCodeThread(*thread, &exit_code);
211 CloseHandle(*thread);
214 /**********************************************************************
215 Initialize mutex
216 ***********************************************************************/
217 void fc_init_mutex(fc_mutex *mutex)
219 *mutex = CreateMutex(NULL, FALSE, NULL);
222 /**********************************************************************
223 Destroy mutex
224 ***********************************************************************/
225 void fc_destroy_mutex(fc_mutex *mutex)
227 CloseHandle(*mutex);
230 /**********************************************************************
231 Lock mutex
232 ***********************************************************************/
233 void fc_allocate_mutex(fc_mutex *mutex)
235 WaitForSingleObject(*mutex, INFINITE);
238 /**********************************************************************
239 Release mutex
240 ***********************************************************************/
241 void fc_release_mutex(fc_mutex *mutex)
243 ReleaseMutex(*mutex);
246 /* TODO: Windows thread condition variable support.
247 * Currently related functions are always dummy ones below
248 * (see #ifndef HAVE_THREAD_COND) */
250 #else /* No thread implementation */
252 #error "No working thread implementation"
254 #endif /* HAVE_PTHREAD || HAVE_WINTHREADS */
257 #ifndef HAVE_THREAD_COND
259 /* Dummy thread condition variable functions */
261 /**********************************************************************
262 Dummy fc_thread_cond_init()
263 ***********************************************************************/
264 void fc_thread_cond_init(fc_thread_cond *cond)
267 /**********************************************************************
268 Dummy fc_thread_cond_destroy()
269 ***********************************************************************/
270 void fc_thread_cond_destroy(fc_thread_cond *cond)
273 /**********************************************************************
274 Dummy fc_thread_cond_wait()
275 ***********************************************************************/
276 void fc_thread_cond_wait(fc_thread_cond *cond, fc_mutex *mutex)
279 /**********************************************************************
280 Dummy fc_thread_cond_signal()
281 ***********************************************************************/
282 void fc_thread_cond_signal(fc_thread_cond *cond)
285 #endif /* !HAVE_THREAD_COND */
287 /**********************************************************************
288 Has freeciv thread condition variable implementation
289 ***********************************************************************/
290 bool has_thread_cond_impl(void)
292 #ifdef HAVE_THREAD_COND
293 return TRUE;
294 #else
295 return FALSE;
296 #endif