ObjFW
|
00001 /* 00002 * Copyright (c) 2008, 2009, 2010, 2011, 2012 00003 * Jonathan Schleifer <js@webkeks.org> 00004 * 00005 * All rights reserved. 00006 * 00007 * This file is part of ObjFW. It may be distributed under the terms of the 00008 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in 00009 * the packaging of this file. 00010 * 00011 * Alternatively, it may be distributed under the terms of the GNU General 00012 * Public License, either version 2 or 3, which can be found in the file 00013 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this 00014 * file. 00015 */ 00016 00017 #import "objfw-defs.h" 00018 00019 #if !defined(OF_THREADS) || (!defined(OF_HAVE_PTHREADS) && !defined(_WIN32)) 00020 # error No threads available! 00021 #endif 00022 00023 #import "macros.h" 00024 00025 #if defined(OF_HAVE_PTHREADS) 00026 # include <pthread.h> 00027 typedef pthread_t of_thread_t; 00028 typedef pthread_key_t of_tlskey_t; 00029 typedef pthread_mutex_t of_mutex_t; 00030 typedef pthread_cond_t of_condition_t; 00031 #elif defined(_WIN32) 00032 # include <windows.h> 00033 typedef HANDLE of_thread_t; 00034 typedef DWORD of_tlskey_t; 00035 typedef CRITICAL_SECTION of_mutex_t; 00036 typedef struct { 00037 HANDLE event; 00038 int count; 00039 } of_condition_t; 00040 #endif 00041 00042 #if defined(OF_ATOMIC_OPS) 00043 # import "atomic.h" 00044 typedef volatile int of_spinlock_t; 00045 # define OF_SPINCOUNT 10 00046 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) 00047 typedef pthread_spinlock_t of_spinlock_t; 00048 #else 00049 typedef of_mutex_t of_spinlock_t; 00050 #endif 00051 00052 #if defined(OF_HAVE_PTHREADS) 00053 # define of_thread_is_current(t) pthread_equal(t, pthread_self()) 00054 # define of_thread_current pthread_self 00055 #elif defined(_WIN32) 00056 # define of_thread_is_current(t) (t == GetCurrentThread()) 00057 # define of_thread_current GetCurrentThread 00058 #endif 00059 00060 static OF_INLINE BOOL 00061 of_thread_new(of_thread_t *thread, id (*main)(id), id data) 00062 { 00063 #if defined(OF_HAVE_PTHREADS) 00064 return !pthread_create(thread, NULL, (void*(*)(void*))main, 00065 (void*)data); 00066 #elif defined(_WIN32) 00067 *thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, 00068 (void*)data, 0, NULL); 00069 00070 return (thread != NULL); 00071 #endif 00072 } 00073 00074 static OF_INLINE BOOL 00075 of_thread_join(of_thread_t thread) 00076 { 00077 #if defined(OF_HAVE_PTHREADS) 00078 void *ret; 00079 00080 if (pthread_join(thread, &ret)) 00081 return NO; 00082 00083 return (ret != PTHREAD_CANCELED); 00084 #elif defined(_WIN32) 00085 if (WaitForSingleObject(thread, INFINITE)) 00086 return NO; 00087 00088 CloseHandle(thread); 00089 00090 return YES; 00091 #endif 00092 } 00093 00094 static OF_INLINE BOOL 00095 of_thread_detach(of_thread_t thread) 00096 { 00097 #if defined(OF_HAVE_PTHREADS) 00098 return !pthread_detach(thread); 00099 #elif defined(_WIN32) 00100 /* FIXME */ 00101 return YES; 00102 #endif 00103 } 00104 00105 static OF_INLINE void 00106 of_thread_exit(void) 00107 { 00108 #if defined(OF_HAVE_PTHREADS) 00109 pthread_exit(NULL); 00110 #elif defined(_WIN32) 00111 ExitThread(0); 00112 #endif 00113 } 00114 00115 static OF_INLINE BOOL 00116 of_mutex_new(of_mutex_t *mutex) 00117 { 00118 #if defined(OF_HAVE_PTHREADS) 00119 return !pthread_mutex_init(mutex, NULL); 00120 #elif defined(_WIN32) 00121 InitializeCriticalSection(mutex); 00122 return YES; 00123 #endif 00124 } 00125 00126 static OF_INLINE BOOL 00127 of_mutex_free(of_mutex_t *mutex) 00128 { 00129 #if defined(OF_HAVE_PTHREADS) 00130 return !pthread_mutex_destroy(mutex); 00131 #elif defined(_WIN32) 00132 DeleteCriticalSection(mutex); 00133 return YES; 00134 #endif 00135 } 00136 00137 static OF_INLINE BOOL 00138 of_mutex_lock(of_mutex_t *mutex) 00139 { 00140 #if defined(OF_HAVE_PTHREADS) 00141 return !pthread_mutex_lock(mutex); 00142 #elif defined(_WIN32) 00143 EnterCriticalSection(mutex); 00144 return YES; 00145 #endif 00146 } 00147 00148 static OF_INLINE BOOL 00149 of_mutex_trylock(of_mutex_t *mutex) 00150 { 00151 #if defined(OF_HAVE_PTHREADS) 00152 return !pthread_mutex_trylock(mutex); 00153 #elif defined(_WIN32) 00154 return TryEnterCriticalSection(mutex); 00155 #endif 00156 } 00157 00158 static OF_INLINE BOOL 00159 of_mutex_unlock(of_mutex_t *mutex) 00160 { 00161 #if defined(OF_HAVE_PTHREADS) 00162 return !pthread_mutex_unlock(mutex); 00163 #elif defined(_WIN32) 00164 LeaveCriticalSection(mutex); 00165 return YES; 00166 #endif 00167 } 00168 00169 static OF_INLINE BOOL 00170 of_condition_new(of_condition_t *condition) 00171 { 00172 #if defined(OF_HAVE_PTHREADS) 00173 return !pthread_cond_init(condition, NULL); 00174 #elif defined(_WIN32) 00175 condition->count = 0; 00176 00177 if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL) 00178 return NO; 00179 00180 return YES; 00181 #endif 00182 } 00183 00184 static OF_INLINE BOOL 00185 of_condition_wait(of_condition_t *condition, of_mutex_t *mutex) 00186 { 00187 #if defined(OF_HAVE_PTHREADS) 00188 return !pthread_cond_wait(condition, mutex); 00189 #elif defined(_WIN32) 00190 if (!of_mutex_unlock(mutex)) 00191 return NO; 00192 00193 of_atomic_inc_int(&condition->count); 00194 00195 if (WaitForSingleObject(condition->event, INFINITE) != WAIT_OBJECT_0) { 00196 of_mutex_lock(mutex); 00197 return NO; 00198 } 00199 00200 of_atomic_dec_int(&condition->count); 00201 00202 if (!of_mutex_lock(mutex)) 00203 return NO; 00204 00205 return YES; 00206 #endif 00207 } 00208 00209 static OF_INLINE BOOL 00210 of_condition_signal(of_condition_t *condition) 00211 { 00212 #if defined(OF_HAVE_PTHREADS) 00213 return !pthread_cond_signal(condition); 00214 #elif defined(_WIN32) 00215 return SetEvent(condition->event); 00216 #endif 00217 } 00218 00219 static OF_INLINE BOOL 00220 of_condition_broadcast(of_condition_t *condition) 00221 { 00222 #if defined(OF_HAVE_PTHREADS) 00223 return !pthread_cond_broadcast(condition); 00224 #elif defined(_WIN32) 00225 size_t i; 00226 00227 for (i = 0; i < condition->count; i++) 00228 if (!SetEvent(condition->event)) 00229 return NO; 00230 00231 return YES; 00232 #endif 00233 } 00234 00235 static OF_INLINE BOOL 00236 of_condition_free(of_condition_t *condition) 00237 { 00238 #if defined(OF_HAVE_PTHREADS) 00239 return !pthread_cond_destroy(condition); 00240 #elif defined(_WIN32) 00241 if (condition->count) 00242 return NO; 00243 00244 return CloseHandle(condition->event); 00245 #endif 00246 } 00247 00248 static OF_INLINE BOOL 00249 of_tlskey_new(of_tlskey_t *key) 00250 { 00251 #if defined(OF_HAVE_PTHREADS) 00252 return !pthread_key_create(key, NULL); 00253 #elif defined(_WIN32) 00254 return ((*key = TlsAlloc()) != TLS_OUT_OF_INDEXES); 00255 #endif 00256 } 00257 00258 static OF_INLINE id 00259 of_tlskey_get(of_tlskey_t key) 00260 { 00261 #if defined(OF_HAVE_PTHREADS) 00262 void *ret = pthread_getspecific(key); 00263 #elif defined(_WIN32) 00264 void *ret = TlsGetValue(key); 00265 #endif 00266 00267 /* NULL and nil might be different! */ 00268 if (ret == NULL) 00269 return nil; 00270 00271 return (id)ret; 00272 } 00273 00274 static OF_INLINE BOOL 00275 of_tlskey_set(of_tlskey_t key, id obj) 00276 { 00277 void *ptr = (obj != nil ? (void*)obj : NULL); 00278 00279 #if defined(OF_HAVE_PTHREADS) 00280 return !pthread_setspecific(key, ptr); 00281 #elif defined(_WIN32) 00282 return TlsSetValue(key, ptr); 00283 #endif 00284 } 00285 00286 static OF_INLINE BOOL 00287 of_tlskey_free(of_tlskey_t key) 00288 { 00289 #if defined(OF_HAVE_PTHREADS) 00290 return !pthread_key_delete(key); 00291 #elif defined(_WIN32) 00292 return TlsFree(key); 00293 #endif 00294 } 00295 00296 static OF_INLINE BOOL 00297 of_spinlock_new(of_spinlock_t *spinlock) 00298 { 00299 #if defined(OF_ATOMIC_OPS) 00300 *spinlock = 0; 00301 return YES; 00302 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) 00303 return !pthread_spin_init(spinlock, 0); 00304 #else 00305 return of_mutex_new(spinlock); 00306 #endif 00307 } 00308 00309 static OF_INLINE BOOL 00310 of_spinlock_trylock(of_spinlock_t *spinlock) 00311 { 00312 #if defined(OF_ATOMIC_OPS) 00313 return of_atomic_cmpswap_int(spinlock, 0, 1); 00314 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) 00315 return !pthread_spin_trylock(spinlock); 00316 #else 00317 return of_mutex_trylock(spinlock); 00318 #endif 00319 } 00320 00321 static OF_INLINE BOOL 00322 of_spinlock_lock(of_spinlock_t *spinlock) 00323 { 00324 #if defined(OF_ATOMIC_OPS) 00325 # if defined(OF_HAVE_SCHED_YIELD) || defined(_WIN32) 00326 int i; 00327 00328 for (i = 0; i < OF_SPINCOUNT; i++) 00329 if (of_spinlock_trylock(spinlock)) 00330 return YES; 00331 00332 while (!of_spinlock_trylock(spinlock)) 00333 # ifndef _WIN32 00334 sched_yield(); 00335 # else 00336 Sleep(0); 00337 # endif 00338 # else 00339 while (!of_spinlock_trylock(spinlock)); 00340 # endif 00341 00342 return YES; 00343 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) 00344 return !pthread_spin_lock(spinlock); 00345 #else 00346 return of_mutex_lock(spinlock); 00347 #endif 00348 } 00349 00350 static OF_INLINE BOOL 00351 of_spinlock_unlock(of_spinlock_t *spinlock) 00352 { 00353 #if defined(OF_ATOMIC_OPS) 00354 *spinlock = 0; 00355 return YES; 00356 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) 00357 return !pthread_spin_unlock(spinlock); 00358 #else 00359 return of_mutex_unlock(spinlock); 00360 #endif 00361 } 00362 00363 static OF_INLINE BOOL 00364 of_spinlock_free(of_spinlock_t *spinlock) 00365 { 00366 #if defined(OF_ATOMIC_OPS) 00367 return YES; 00368 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS) 00369 return !pthread_spin_destroy(spinlock); 00370 #else 00371 return of_mutex_free(spinlock); 00372 #endif 00373 }