17 #import "objfw-defs.h"
19 #if !defined(OF_THREADS) || (!defined(OF_HAVE_PTHREADS) && !defined(_WIN32))
20 # error No threads available!
25 #if defined(OF_HAVE_PTHREADS)
27 typedef pthread_t of_thread_t;
28 typedef pthread_key_t of_tlskey_t;
29 typedef pthread_mutex_t of_mutex_t;
30 typedef pthread_cond_t of_condition_t;
33 typedef HANDLE of_thread_t;
34 typedef DWORD of_tlskey_t;
35 typedef CRITICAL_SECTION of_mutex_t;
42 #if defined(OF_ATOMIC_OPS)
44 typedef volatile int of_spinlock_t;
45 # define OF_SPINCOUNT 10
46 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
47 typedef pthread_spinlock_t of_spinlock_t;
49 typedef of_mutex_t of_spinlock_t;
52 #ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
53 # define of_rmutex_t of_mutex_t
61 #if defined(OF_HAVE_PTHREADS)
62 # define of_thread_is_current(t) pthread_equal(t, pthread_self())
63 # define of_thread_current pthread_self
65 # define of_thread_is_current(t) (t == GetCurrentThread())
66 # define of_thread_current GetCurrentThread
70 of_thread_new(of_thread_t *thread,
id (*
function)(
id),
id data)
72 #if defined(OF_HAVE_PTHREADS)
73 return !pthread_create(thread, NULL, (
void*(*)(
void*))
function,
74 (__bridge
void*)data);
76 *thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
function,
77 (__bridge
void*)data, 0, NULL);
79 return (thread != NULL);
84 of_thread_join(of_thread_t thread)
86 #if defined(OF_HAVE_PTHREADS)
89 if (pthread_join(thread, &ret))
92 return (ret != PTHREAD_CANCELED);
94 if (WaitForSingleObject(thread, INFINITE))
103 static OF_INLINE BOOL
104 of_thread_detach(of_thread_t thread)
106 #if defined(OF_HAVE_PTHREADS)
107 return !pthread_detach(thread);
108 #elif defined(_WIN32)
114 static OF_INLINE
void
117 #if defined(OF_HAVE_PTHREADS)
119 #elif defined(_WIN32)
124 static OF_INLINE BOOL
125 of_mutex_new(of_mutex_t *mutex)
127 #if defined(OF_HAVE_PTHREADS)
128 return !pthread_mutex_init(mutex, NULL);
129 #elif defined(_WIN32)
130 InitializeCriticalSection(mutex);
135 static OF_INLINE BOOL
136 of_mutex_free(of_mutex_t *mutex)
138 #if defined(OF_HAVE_PTHREADS)
139 return !pthread_mutex_destroy(mutex);
140 #elif defined(_WIN32)
141 DeleteCriticalSection(mutex);
146 static OF_INLINE BOOL
147 of_mutex_lock(of_mutex_t *mutex)
149 #if defined(OF_HAVE_PTHREADS)
150 return !pthread_mutex_lock(mutex);
151 #elif defined(_WIN32)
152 EnterCriticalSection(mutex);
157 static OF_INLINE BOOL
158 of_mutex_trylock(of_mutex_t *mutex)
160 #if defined(OF_HAVE_PTHREADS)
161 return !pthread_mutex_trylock(mutex);
162 #elif defined(_WIN32)
163 return TryEnterCriticalSection(mutex);
167 static OF_INLINE BOOL
168 of_mutex_unlock(of_mutex_t *mutex)
170 #if defined(OF_HAVE_PTHREADS)
171 return !pthread_mutex_unlock(mutex);
172 #elif defined(_WIN32)
173 LeaveCriticalSection(mutex);
178 static OF_INLINE BOOL
179 of_condition_new(of_condition_t *condition)
181 #if defined(OF_HAVE_PTHREADS)
182 return !pthread_cond_init(condition, NULL);
183 #elif defined(_WIN32)
184 condition->count = 0;
186 if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL)
193 static OF_INLINE BOOL
194 of_condition_wait(of_condition_t *condition, of_mutex_t *mutex)
196 #if defined(OF_HAVE_PTHREADS)
197 return !pthread_cond_wait(condition, mutex);
198 #elif defined(_WIN32)
199 if (!of_mutex_unlock(mutex))
202 of_atomic_inc_int(&condition->count);
204 if (WaitForSingleObject(condition->event, INFINITE) != WAIT_OBJECT_0) {
205 of_mutex_lock(mutex);
209 of_atomic_dec_int(&condition->count);
211 if (!of_mutex_lock(mutex))
218 static OF_INLINE BOOL
219 of_condition_signal(of_condition_t *condition)
221 #if defined(OF_HAVE_PTHREADS)
222 return !pthread_cond_signal(condition);
223 #elif defined(_WIN32)
224 return SetEvent(condition->event);
228 static OF_INLINE BOOL
229 of_condition_broadcast(of_condition_t *condition)
231 #if defined(OF_HAVE_PTHREADS)
232 return !pthread_cond_broadcast(condition);
233 #elif defined(_WIN32)
236 for (i = 0; i < condition->count; i++)
237 if (!SetEvent(condition->event))
244 static OF_INLINE BOOL
245 of_condition_free(of_condition_t *condition)
247 #if defined(OF_HAVE_PTHREADS)
248 return !pthread_cond_destroy(condition);
249 #elif defined(_WIN32)
250 if (condition->count)
253 return CloseHandle(condition->event);
257 static OF_INLINE BOOL
258 of_tlskey_new(of_tlskey_t *key)
260 #if defined(OF_HAVE_PTHREADS)
261 return !pthread_key_create(key, NULL);
262 #elif defined(_WIN32)
263 return ((*key = TlsAlloc()) != TLS_OUT_OF_INDEXES);
267 static OF_INLINE
void*
268 of_tlskey_get(of_tlskey_t key)
270 #if defined(OF_HAVE_PTHREADS)
271 return pthread_getspecific(key);
272 #elif defined(_WIN32)
273 return TlsGetValue(key);
277 static OF_INLINE BOOL
278 of_tlskey_set(of_tlskey_t key,
void *ptr)
280 #if defined(OF_HAVE_PTHREADS)
281 return !pthread_setspecific(key, ptr);
282 #elif defined(_WIN32)
283 return TlsSetValue(key, ptr);
287 static OF_INLINE BOOL
288 of_tlskey_free(of_tlskey_t key)
290 #if defined(OF_HAVE_PTHREADS)
291 return !pthread_key_delete(key);
292 #elif defined(_WIN32)
297 static OF_INLINE BOOL
298 of_spinlock_new(of_spinlock_t *spinlock)
300 #if defined(OF_ATOMIC_OPS)
303 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
304 return !pthread_spin_init(spinlock, 0);
306 return of_mutex_new(spinlock);
310 static OF_INLINE BOOL
311 of_spinlock_trylock(of_spinlock_t *spinlock)
313 #if defined(OF_ATOMIC_OPS)
314 return of_atomic_cmpswap_int(spinlock, 0, 1);
315 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
316 return !pthread_spin_trylock(spinlock);
318 return of_mutex_trylock(spinlock);
322 static OF_INLINE BOOL
323 of_spinlock_lock(of_spinlock_t *spinlock)
325 #if defined(OF_ATOMIC_OPS)
326 # if defined(OF_HAVE_SCHED_YIELD) || defined(_WIN32)
329 for (i = 0; i < OF_SPINCOUNT; i++)
330 if (of_spinlock_trylock(spinlock))
333 while (!of_spinlock_trylock(spinlock))
340 while (!of_spinlock_trylock(spinlock));
344 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
345 return !pthread_spin_lock(spinlock);
347 return of_mutex_lock(spinlock);
351 static OF_INLINE BOOL
352 of_spinlock_unlock(of_spinlock_t *spinlock)
354 #if defined(OF_ATOMIC_OPS)
357 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
358 return !pthread_spin_unlock(spinlock);
360 return of_mutex_unlock(spinlock);
364 static OF_INLINE BOOL
365 of_spinlock_free(of_spinlock_t *spinlock)
367 #if defined(OF_ATOMIC_OPS)
369 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
370 return !pthread_spin_destroy(spinlock);
372 return of_mutex_free(spinlock);
376 #ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
377 static OF_INLINE BOOL
378 of_rmutex_new(of_mutex_t *mutex)
380 pthread_mutexattr_t attr;
382 if (pthread_mutexattr_init(&attr))
385 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
388 if (pthread_mutex_init(mutex, &attr))
391 if (pthread_mutexattr_destroy(&attr))
397 # define of_rmutex_lock of_mutex_lock
398 # define of_rmutex_trylock of_mutex_trylock
399 # define of_rmutex_unlock of_mutex_unlock
400 # define of_rmutex_free of_mutex_free
402 static OF_INLINE BOOL
403 of_rmutex_new(of_rmutex_t *rmutex)
405 if (!of_mutex_new(&rmutex->mutex))
408 if (!of_tlskey_new(&rmutex->count))
414 static OF_INLINE BOOL
415 of_rmutex_lock(of_rmutex_t *rmutex)
417 uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count);
420 if (!of_tlskey_set(rmutex->count, (
void*)(count + 1)))
425 if (!of_mutex_lock(&rmutex->mutex))
428 if (!of_tlskey_set(rmutex->count, (
void*)1)) {
429 of_mutex_unlock(&rmutex->mutex);
436 static OF_INLINE BOOL
437 of_rmutex_trylock(of_rmutex_t *rmutex)
439 uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count);
442 if (!of_tlskey_set(rmutex->count, (
void*)(count + 1)))
447 if (!of_mutex_trylock(&rmutex->mutex))
450 if (!of_tlskey_set(rmutex->count, (
void*)1)) {
451 of_mutex_unlock(&rmutex->mutex);
458 static OF_INLINE BOOL
459 of_rmutex_unlock(of_rmutex_t *rmutex)
461 uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count);
464 if (!of_tlskey_set(rmutex->count, (
void*)(count - 1)))
469 if (!of_tlskey_set(rmutex->count, (
void*)0))
472 if (!of_mutex_unlock(&rmutex->mutex))
478 static OF_INLINE BOOL
479 of_rmutex_free(of_rmutex_t *rmutex)
481 if (!of_mutex_free(&rmutex->mutex))
484 if (!of_tlskey_free(rmutex->count))