00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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) ? NO : YES);
00066 #elif defined(_WIN32)
00067 *thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main,
00068 (void*)data, 0, NULL);
00069
00070 return (thread == NULL ? NO : YES);
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 ? YES : NO);
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 void
00095 of_thread_exit()
00096 {
00097 #if defined(OF_HAVE_PTHREADS)
00098 pthread_exit(NULL);
00099 #elif defined(_WIN32)
00100 ExitThread(0);
00101 #endif
00102 }
00103
00104 static OF_INLINE BOOL
00105 of_mutex_new(of_mutex_t *mutex)
00106 {
00107 #if defined(OF_HAVE_PTHREADS)
00108 return (pthread_mutex_init(mutex, NULL) ? NO : YES);
00109 #elif defined(_WIN32)
00110 InitializeCriticalSection(mutex);
00111 return YES;
00112 #endif
00113 }
00114
00115 static OF_INLINE BOOL
00116 of_mutex_free(of_mutex_t *mutex)
00117 {
00118 #if defined(OF_HAVE_PTHREADS)
00119 return (pthread_mutex_destroy(mutex) ? NO : YES);
00120 #elif defined(_WIN32)
00121 DeleteCriticalSection(mutex);
00122 return YES;
00123 #endif
00124 }
00125
00126 static OF_INLINE BOOL
00127 of_mutex_lock(of_mutex_t *mutex)
00128 {
00129 #if defined(OF_HAVE_PTHREADS)
00130 return (pthread_mutex_lock(mutex) ? NO : YES);
00131 #elif defined(_WIN32)
00132 EnterCriticalSection(mutex);
00133 return YES;
00134 #endif
00135 }
00136
00137 static OF_INLINE BOOL
00138 of_mutex_trylock(of_mutex_t *mutex)
00139 {
00140 #if defined(OF_HAVE_PTHREADS)
00141 return (pthread_mutex_trylock(mutex) ? NO : YES);
00142 #elif defined(_WIN32)
00143 return (TryEnterCriticalSection(mutex) ? YES : NO);
00144 #endif
00145 }
00146
00147 static OF_INLINE BOOL
00148 of_mutex_unlock(of_mutex_t *mutex)
00149 {
00150 #if defined(OF_HAVE_PTHREADS)
00151 return (pthread_mutex_unlock(mutex) ? NO : YES);
00152 #elif defined(_WIN32)
00153 LeaveCriticalSection(mutex);
00154 return YES;
00155 #endif
00156 }
00157
00158 static OF_INLINE BOOL
00159 of_condition_new(of_condition_t *condition)
00160 {
00161 #if defined(OF_HAVE_PTHREADS)
00162 return (pthread_cond_init(condition, NULL) ? NO : YES);
00163 #elif defined(_WIN32)
00164 condition->count = 0;
00165
00166 if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL)
00167 return NO;
00168
00169 return YES;
00170 #endif
00171 }
00172
00173 static OF_INLINE BOOL
00174 of_condition_wait(of_condition_t *condition, of_mutex_t *mutex)
00175 {
00176 #if defined(OF_HAVE_PTHREADS)
00177 return (pthread_cond_wait(condition, mutex) ? NO : YES);
00178 #elif defined(_WIN32)
00179 if (!of_mutex_unlock(mutex))
00180 return NO;
00181
00182 of_atomic_inc_int(&condition->count);
00183
00184 if (WaitForSingleObject(condition->event, INFINITE) != WAIT_OBJECT_0) {
00185 of_mutex_lock(mutex);
00186 return NO;
00187 }
00188
00189 of_atomic_dec_int(&condition->count);
00190
00191 if (!of_mutex_lock(mutex))
00192 return NO;
00193
00194 return YES;
00195 #endif
00196 }
00197
00198 static OF_INLINE BOOL
00199 of_condition_signal(of_condition_t *condition)
00200 {
00201 #if defined(OF_HAVE_PTHREADS)
00202 return (pthread_cond_signal(condition) ? NO : YES);
00203 #elif defined(_WIN32)
00204 return (SetEvent(condition->event) ? YES : NO);
00205 #endif
00206 }
00207
00208 static OF_INLINE BOOL
00209 of_condition_broadcast(of_condition_t *condition)
00210 {
00211 #if defined(OF_HAVE_PTHREADS)
00212 return (pthread_cond_broadcast(condition) ? NO : YES);
00213 #elif defined(_WIN32)
00214 size_t i;
00215
00216 for (i = 0; i < condition->count; i++)
00217 if (!SetEvent(condition->event))
00218 return NO;
00219
00220 return YES;
00221 #endif
00222 }
00223
00224 static OF_INLINE BOOL
00225 of_condition_free(of_condition_t *condition)
00226 {
00227 #if defined(OF_HAVE_PTHREADS)
00228 return (pthread_cond_destroy(condition) ? NO : YES);
00229 #elif defined(_WIN32)
00230 if (condition->count)
00231 return NO;
00232
00233 return (CloseHandle(condition->event) ? YES : NO);
00234 #endif
00235 }
00236
00237 static OF_INLINE BOOL
00238 of_tlskey_new(of_tlskey_t *key)
00239 {
00240 #if defined(OF_HAVE_PTHREADS)
00241 return (pthread_key_create(key, NULL) ? NO : YES);
00242 #elif defined(_WIN32)
00243 return ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES ? NO : YES);
00244 #endif
00245 }
00246
00247 static OF_INLINE id
00248 of_tlskey_get(of_tlskey_t key)
00249 {
00250 #if defined(OF_HAVE_PTHREADS)
00251 void *ret = pthread_getspecific(key);
00252 #elif defined(_WIN32)
00253 void *ret = TlsGetValue(key);
00254 #endif
00255
00256
00257 if (ret == NULL)
00258 return nil;
00259
00260 return (id)ret;
00261 }
00262
00263 static OF_INLINE BOOL
00264 of_tlskey_set(of_tlskey_t key, id obj)
00265 {
00266 void *p = (obj != nil ? (void*)obj : NULL);
00267
00268 #if defined(OF_HAVE_PTHREADS)
00269 return (pthread_setspecific(key, p) ? NO : YES);
00270 #elif defined(_WIN32)
00271 return (TlsSetValue(key, p) ? YES : NO);
00272 #endif
00273 }
00274
00275 static OF_INLINE BOOL
00276 of_tlskey_free(of_tlskey_t key)
00277 {
00278 #if defined(OF_HAVE_PTHREADS)
00279 return (pthread_key_delete(key) ? NO : YES);
00280 #elif defined(_WIN32)
00281 return (TlsFree(key) ? YES : NO);
00282 #endif
00283 }
00284
00285 static OF_INLINE BOOL
00286 of_spinlock_new(of_spinlock_t *s)
00287 {
00288 #if defined(OF_ATOMIC_OPS)
00289 *s = 0;
00290 return YES;
00291 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00292 return (pthread_spin_init(s, 0) ? NO : YES);
00293 #else
00294 return of_mutex_new(s);
00295 #endif
00296 }
00297
00298 static OF_INLINE BOOL
00299 of_spinlock_trylock(of_spinlock_t *s)
00300 {
00301 #if defined(OF_ATOMIC_OPS)
00302 return (of_atomic_cmpswap_int(s, 0, 1) ? YES : NO);
00303 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00304 return (pthread_spin_trylock(s) ? NO : YES);
00305 #else
00306 return of_mutex_trylock(s);
00307 #endif
00308 }
00309
00310 static OF_INLINE BOOL
00311 of_spinlock_lock(of_spinlock_t *s)
00312 {
00313 #if defined(OF_ATOMIC_OPS)
00314 # if defined(OF_HAVE_SCHED_YIELD) || defined(_WIN32)
00315 int i;
00316
00317 for (i = 0; i < OF_SPINCOUNT; i++)
00318 if (of_spinlock_trylock(s))
00319 return YES;
00320
00321 while (!of_spinlock_trylock(s))
00322 # ifndef _WIN32
00323 sched_yield();
00324 # else
00325 Sleep(0);
00326 # endif
00327 # else
00328 while (!of_spinlock_trylock(s));
00329 # endif
00330
00331 return YES;
00332 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00333 return (pthread_spin_lock(s) ? NO : YES);
00334 #else
00335 return of_mutex_lock(s);
00336 #endif
00337 }
00338
00339 static OF_INLINE BOOL
00340 of_spinlock_unlock(of_spinlock_t *s)
00341 {
00342 #if defined(OF_ATOMIC_OPS)
00343 *s = 0;
00344 return YES;
00345 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00346 return (pthread_spin_unlock(s) ? NO : YES);
00347 #else
00348 return of_mutex_unlock(s);
00349 #endif
00350 }
00351
00352 static OF_INLINE BOOL
00353 of_spinlock_free(of_spinlock_t *s)
00354 {
00355 #if defined(OF_ATOMIC_OPS)
00356 return YES;
00357 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00358 return (pthread_spin_destroy(s) ? NO : YES);
00359 #else
00360 return of_mutex_free(s);
00361 #endif
00362 }