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_mutex_t of_mutex_t;
00029 typedef pthread_key_t of_tlskey_t;
00030 #elif defined(_WIN32)
00031 # include <windows.h>
00032 typedef HANDLE of_thread_t;
00033 typedef CRITICAL_SECTION of_mutex_t;
00034 typedef DWORD of_tlskey_t;
00035 #endif
00036
00037 #if defined(OF_ATOMIC_OPS)
00038 # import "atomic.h"
00039 typedef volatile int of_spinlock_t;
00040 # define OF_SPINCOUNT 10
00041 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00042 typedef pthread_spinlock_t of_spinlock_t;
00043 #else
00044 typedef of_mutex_t of_spinlock_t;
00045 #endif
00046
00047 #if defined(OF_HAVE_PTHREADS)
00048 # define of_thread_is_current(t) pthread_equal(t, pthread_self())
00049 # define of_thread_current() pthread_self()
00050 #elif defined(_WIN32)
00051 # define of_thread_is_current(t) (t == GetCurrentThread())
00052 # define of_thread_current() GetCurrentThread()
00053 #endif
00054
00055 static OF_INLINE BOOL
00056 of_thread_new(of_thread_t *thread, id (*main)(id), id data)
00057 {
00058 #if defined(OF_HAVE_PTHREADS)
00059 return (pthread_create(thread, NULL, (void*(*)(void*))main,
00060 (void*)data) ? NO : YES);
00061 #elif defined(_WIN32)
00062 *thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main,
00063 (void*)data, 0, NULL);
00064
00065 return (thread == NULL ? NO : YES);
00066 #endif
00067 }
00068
00069 static OF_INLINE BOOL
00070 of_thread_join(of_thread_t thread)
00071 {
00072 #if defined(OF_HAVE_PTHREADS)
00073 void *ret;
00074
00075 if (pthread_join(thread, &ret))
00076 return NO;
00077
00078 return (ret != PTHREAD_CANCELED ? YES : NO);
00079 #elif defined(_WIN32)
00080 if (WaitForSingleObject(thread, INFINITE))
00081 return NO;
00082
00083 CloseHandle(thread);
00084
00085 return YES;
00086 #endif
00087 }
00088
00089 static OF_INLINE void
00090 of_thread_exit()
00091 {
00092 #if defined(OF_HAVE_PTHREADS)
00093 pthread_exit(NULL);
00094 #elif defined(_WIN32)
00095 ExitThread(0);
00096 #endif
00097 }
00098
00099 static OF_INLINE BOOL
00100 of_mutex_new(of_mutex_t *mutex)
00101 {
00102 #if defined(OF_HAVE_PTHREADS)
00103 return (pthread_mutex_init(mutex, NULL) ? NO : YES);
00104 #elif defined(_WIN32)
00105 InitializeCriticalSection(mutex);
00106 return YES;
00107 #endif
00108 }
00109
00110 static OF_INLINE BOOL
00111 of_mutex_free(of_mutex_t *mutex)
00112 {
00113 #if defined(OF_HAVE_PTHREADS)
00114 return (pthread_mutex_destroy(mutex) ? NO : YES);
00115 #elif defined(_WIN32)
00116 DeleteCriticalSection(mutex);
00117 return YES;
00118 #endif
00119 }
00120
00121 static OF_INLINE BOOL
00122 of_mutex_lock(of_mutex_t *mutex)
00123 {
00124 #if defined(OF_HAVE_PTHREADS)
00125 return (pthread_mutex_lock(mutex) ? NO : YES);
00126 #elif defined(_WIN32)
00127 EnterCriticalSection(mutex);
00128 return YES;
00129 #endif
00130 }
00131
00132 static OF_INLINE BOOL
00133 of_mutex_trylock(of_mutex_t *mutex)
00134 {
00135 #if defined(OF_HAVE_PTHREADS)
00136 return (pthread_mutex_trylock(mutex) ? NO : YES);
00137 #elif defined(_WIN32)
00138 return (TryEnterCriticalSection(mutex) ? YES : NO);
00139 #endif
00140 }
00141
00142 static OF_INLINE BOOL
00143 of_mutex_unlock(of_mutex_t *mutex)
00144 {
00145 #if defined(OF_HAVE_PTHREADS)
00146 return (pthread_mutex_unlock(mutex) ? NO : YES);
00147 #elif defined(_WIN32)
00148 LeaveCriticalSection(mutex);
00149 return YES;
00150 #endif
00151 }
00152
00153 static OF_INLINE BOOL
00154 of_tlskey_new(of_tlskey_t *key)
00155 {
00156 #if defined(OF_HAVE_PTHREADS)
00157 return (pthread_key_create(key, NULL) ? NO : YES);
00158 #elif defined(_WIN32)
00159 return ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES ? NO : YES);
00160 #endif
00161 }
00162
00163 static OF_INLINE id
00164 of_tlskey_get(of_tlskey_t key)
00165 {
00166 #if defined(OF_HAVE_PTHREADS)
00167 void *ret = pthread_getspecific(key);
00168 #elif defined(_WIN32)
00169 void *ret = TlsGetValue(key);
00170 #endif
00171
00172
00173 if (ret == NULL)
00174 return nil;
00175
00176 return (id)ret;
00177 }
00178
00179 static OF_INLINE BOOL
00180 of_tlskey_set(of_tlskey_t key, id obj)
00181 {
00182 void *p = (obj != nil ? (void*)obj : NULL);
00183
00184 #if defined(OF_HAVE_PTHREADS)
00185 return (pthread_setspecific(key, p) ? NO : YES);
00186 #elif defined(_WIN32)
00187 return (TlsSetValue(key, p) ? YES : NO);
00188 #endif
00189 }
00190
00191 static OF_INLINE BOOL
00192 of_tlskey_free(of_tlskey_t key)
00193 {
00194 #if defined(OF_HAVE_PTHREADS)
00195 return (pthread_key_delete(key) ? NO : YES);
00196 #elif defined(_WIN32)
00197 return (TlsFree(key) ? YES : NO);
00198 #endif
00199 }
00200
00201 static OF_INLINE BOOL
00202 of_spinlock_new(of_spinlock_t *s)
00203 {
00204 #if defined(OF_ATOMIC_OPS)
00205 *s = 0;
00206 return YES;
00207 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00208 return (pthread_spin_init(s, 0) ? NO : YES);
00209 #else
00210 return of_mutex_new(s);
00211 #endif
00212 }
00213
00214 static OF_INLINE BOOL
00215 of_spinlock_trylock(of_spinlock_t *s)
00216 {
00217 #if defined(OF_ATOMIC_OPS)
00218 return (of_atomic_cmpswap_int(s, 0, 1) ? YES : NO);
00219 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00220 return (pthread_spin_trylock(s) ? NO : YES);
00221 #else
00222 return of_mutex_trylock(s);
00223 #endif
00224 }
00225
00226 static OF_INLINE BOOL
00227 of_spinlock_lock(of_spinlock_t *s)
00228 {
00229 #if defined(OF_ATOMIC_OPS)
00230 # ifdef OF_HAVE_SCHED_YIELD
00231 int i;
00232
00233 for (i = 0; i < OF_SPINCOUNT; i++)
00234 if (of_spinlock_trylock(s))
00235 return YES;
00236
00237 while (!of_spinlock_trylock(s))
00238 sched_yield();
00239 # else
00240 while (!of_spinlock_trylock(s));
00241 # endif
00242
00243 return YES;
00244 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00245 return (pthread_spin_lock(s) ? NO : YES);
00246 #else
00247 return of_mutex_lock(s);
00248 #endif
00249 }
00250
00251 static OF_INLINE BOOL
00252 of_spinlock_unlock(of_spinlock_t *s)
00253 {
00254 #if defined(OF_ATOMIC_OPS)
00255 *s = 0;
00256 return YES;
00257 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00258 return (pthread_spin_unlock(s) ? NO : YES);
00259 #else
00260 return of_mutex_unlock(s);
00261 #endif
00262 }
00263
00264 static OF_INLINE BOOL
00265 of_spinlock_free(of_spinlock_t *s)
00266 {
00267 #if defined(OF_ATOMIC_OPS)
00268 return YES;
00269 #elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
00270 return (pthread_spin_destroy(s) ? NO : YES);
00271 #else
00272 return of_mutex_free(s);
00273 #endif
00274 }