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