![]() |
BlitzMax Extended
0.8.11
Pushing Blitz to the Max.
|
00001 00007 #ifndef BLITZ_THREAD_H 00008 #define BLITZ_THREAD_H 00009 00010 #include "_common.h" 00011 00012 #ifdef BB_OS_LINUX 00013 # include <semaphore.h> 00014 #endif 00015 00016 #ifdef BB_OS_MACOS 00017 # include <mach/semaphore.h> 00018 # include <mach/task.h> 00019 # include <mach/mach_init.h> 00020 00021 # include <libkern/OSAtomic.h> // test 00022 00023 #endif 00024 00025 #ifndef BB_OS_WIN32 00026 # include <pthread.h> 00027 # include <unistd.h> 00028 # include <signal.h> 00029 #endif // !BB_OS_WIN32 00030 00031 BB_BEGIN_DECLS 00032 00033 #ifdef BB_OS_LINUX 00034 typedef pthread_mutex_t bb_mutex_t; 00035 typedef sem_t bb_sem_t; 00036 #endif 00037 00038 #ifdef BB_OS_MACOS 00039 typedef pthread_mutex_t bb_mutex_t; 00040 typedef semaphore_t bb_sem_t; 00041 #endif 00042 00043 #ifdef BB_OS_WIN32 00044 typedef CRITICAL_SECTION bb_mutex_t; 00045 typedef HANDLE bb_sem_t; 00046 #endif 00047 00048 #ifndef BB_OS_WIN32 00049 extern pthread_mutexattr_t _bb_mutexattr; 00050 #endif // !BB_OS_WIN32 00051 00052 // Replacing macros with actual inline functions 00053 #ifdef BB_ENABLE_EXPERIMENTAL 00054 00055 inline bool bb_mutex_init(bb_mutex_t *mutex) 00056 { 00057 #ifdef BB_OS_WIN32 00058 InitializeCriticalSection(mutex); 00059 return true; 00060 #else 00061 return pthread_mutex_init(mutex, &_bb_mutexattr) >= 0; 00062 #endif 00063 } 00064 00065 inline bool bb_mutex_destroy(bb_mutex_t *mutex) 00066 { 00067 #ifdef BB_OS_WIN32 00068 DeleteCriticalSection(mutex); 00069 return true; 00070 #else 00071 return pthread_mutex_destroy(mutex) >= 0; 00072 #endif 00073 } 00074 00075 inline bool bb_mutex_lock(bb_mutex_t *mutex) 00076 { 00077 #ifdef BB_OS_WIN32 00078 DeleteCriticalSection(mutex); 00079 return true; 00080 #else 00081 return pthread_mutex_lock(mutex) >= 0; 00082 #endif 00083 } 00084 00085 inline bool bb_mutex_unlock(bb_mutex_t *mutex) 00086 { 00087 #ifdef BB_OS_WIN32 00088 LeaveCriticalSection(mutex); 00089 return true; 00090 #else 00091 return pthread_mutex_lock(mutex) >= 0; 00092 #endif 00093 } 00094 00095 inline bool bb_mutex_trylock(bb_mutex_t *mutex) 00096 { 00097 #ifdef BB_OS_WIN32 00098 return TryEnterCriticalSection(mutex) != 0; 00099 #else 00100 return pthread_mutex_trylock(mutex) == 0; 00101 #endif 00102 } 00103 00104 00105 00106 inline bool bb_sem_init(bb_sem_t *sem, size_t count) 00107 { 00108 #if defined (BB_OS_LINUX) 00109 return sem_init(sem, 0, count) >= 0; 00110 #elif defined (BB_OS_MACOS) 00111 return semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, count) >= 0; 00112 #elif defined (BB_OS_WIN32) 00113 *sem = CreateSemaphore(0, count, 0x7fffffff, 0); 00114 return *sem != 0; 00115 #endif 00116 } 00117 00118 inline bool bb_sem_destroy(bb_sem_t *sem) 00119 { 00120 #if defined (BB_OS_LINUX) 00121 return sem_destroy(sem); 00122 #elif defined (BB_OS_MACOS) 00123 return semaphore_destroy(mach_task_self(), *sem); 00124 #elif defined (BB_OS_WIN32) 00125 CloseHandle(*sem); 00126 #endif 00127 } 00128 00129 inline bool bb_sem_wait(bb_sem_t *sem) 00130 { 00131 #if defined (BB_OS_LINUX) 00132 return sem_wait(sem); 00133 #elif defined (BB_OS_MACOS) 00134 return semaphore_wait(*sem); 00135 #elif defined (BB_OS_WIN32) 00136 return WaitForSingleObject(*sem, INFINITE); 00137 #endif 00138 } 00139 00140 inline bool bb_sem_post(bb_sem_t *sem) 00141 { 00142 #if defined (BB_OS_LINUX) 00143 return sem_post(sem); 00144 #elif defined (BB_OS_MACOS) 00145 return semaphore_signal(*sem); 00146 #elif defined (BB_OS_WIN32) 00147 return ReleaseSemaphore(*sem, 1, 0); 00148 #endif 00149 } 00150 00151 #else // BB_ENABLE_EXPERIMENTAL 00152 00153 #ifdef BB_OS_WIN32 00154 00155 # define bb_mutex_init(MUTPTR) (InitializeCriticalSection(MUTPTR), 1) 00156 # define bb_mutex_destroy(MUTPTR) DeleteCriticalSection(MUTPTR) 00157 # define bb_mutex_lock(MUTPTR) EnterCriticalSection(MUTPTR) 00158 # define bb_mutex_unlock(MUTPTR) LeaveCriticalSection(MUTPTR) 00159 # define bb_mutex_trylock(MUTPTR) (TryEnterCriticalSection(MUTPTR) != 0) 00160 00161 # define bb_sem_init(SEMPTR,COUNT) ((*(SEMPTR) = CreateSemaphore(0, (COUNT), 0x7fffffff, 0)) != 0) 00162 # define bb_sem_destroy(SEMPTR) CloseHandle(*(SEMPTR)) 00163 # define bb_sem_wait(SEMPTR) WaitForSingleObject(*(SEMPTR), INFINITE) 00164 # define bb_sem_post(SEMPTR) ReleaseSemaphore(*(SEMPTR), 1, 0) 00165 00166 #else // BB_OS_WIN32 00167 00168 extern pthread_mutexattr_t _bb_mutexattr; 00169 00170 # define bb_mutex_init(MUTPTR) (pthread_mutex_init((MUTPTR),&_bb_mutexattr) >= 0) 00171 # define bb_mutex_destroy(MUTPTR) pthread_mutex_destroy(MUTPTR) 00172 # define bb_mutex_lock(MUTPTR) pthread_mutex_lock(MUTPTR) 00173 # define bb_mutex_unlock(MUTPTR) pthread_mutex_unlock(MUTPTR) 00174 # define bb_mutex_trylock(MUTPTR) (pthread_mutex_trylock(MUTPTR) == 0) 00175 00176 #endif // !BB_OS_WIN32 00177 00178 #ifdef BB_OS_MACOS 00179 # define bb_sem_init(SEMPTR,COUNT) (semaphore_create(mach_task_self(), (SEMPTR), SYNC_POLICY_FIFO, (COUNT)) >= 0) 00180 # define bb_sem_destroy(SEMPTR) semaphore_destroy(mach_task_self(), *(SEMPTR)) 00181 # define bb_sem_wait(SEMPTR) semaphore_wait(*(SEMPTR)) 00182 # define bb_sem_post(SEMPTR) semaphore_signal(*(SEMPTR)) 00183 #endif // BB_OS_MACOS 00184 00185 #ifdef BB_OS_LINUX 00186 # define bb_sem_init(SEMPTR, COUNT) (sem_init((SEMPTR), 0, (COUNT)) >= 0) 00187 # define bb_sem_destroy sem_destroy 00188 # define bb_sem_wait sem_wait 00189 # define bb_sem_post sem_post 00190 #endif // BB_OS_LINUX 00191 00192 #endif // !BB_ENABLE_EXPERIMENTAL 00193 00194 #ifdef BB_OS_WIN32 00195 # define BBTHREAD_NUM_REGS 7 00196 #elif BB_CPU_PPC 00197 # define BBTHREAD_NUM_REGS 19 00198 #else 00199 # define BBTHREAD_NUM_REGS 4 00200 #endif 00201 00206 typedef BBObject *(*BBThreadProc)(BBObject*); 00207 00208 typedef struct BBThread BBThread; 00209 00210 #define BBTHREAD_DATA_SIZE 32 00211 00215 struct BBThread 00216 { 00217 BBThread *succ; 00218 BBThreadProc proc; 00219 void *data[BBTHREAD_DATA_SIZE]; 00220 int detached; 00221 void *stackTop; 00222 void *locked_sp; 00223 int locked_regs[BBTHREAD_NUM_REGS]; 00224 #ifdef BB_OS_WIN32 00225 HANDLE handle; 00226 DWORD id; 00227 #else 00228 pthread_t handle; 00229 int suspended; 00230 bb_sem_t runsema; 00231 bb_sem_t acksema; 00232 #endif // !BB_OS_WIN32 00233 }; 00234 00235 // Sets up the threading environment 00236 // Automatically called by bbStartup (blitz_app.c) 00237 void bbThreadStartup(); 00238 00245 BBThread* bbThreadCreate(BBThreadProc entry, BBObject *data); 00246 00250 void bbThreadDetach(BBThread *thread); 00251 00255 BBObject* bbThreadWait(BBThread *thread); 00256 00261 BBThread* bbThreadGetMain(); 00262 00270 BBThread* bbThreadGetCurrent(); 00271 00275 BBInt bbThreadSuspend(BBThread *thread); 00276 00280 BBInt bbThreadResume(BBThread *thread); 00281 00282 00283 00287 BBInt bbThreadAllocData(); 00288 00292 void bbThreadSetData(BBInt index, BBObject *data); 00293 00297 BBObject* bbThreadGetData(BBInt index); 00298 00299 // These MUST be inside a BB_LOCK/BB_UNLOCK 00300 BBThread* _bbThreadLockThreads(); 00301 void _bbThreadUnlockThreads(); 00302 00306 BBInt bbAtomicCAS(volatile BBInt *target, BBInt old_value, BBInt new_value); 00307 00314 BBInt bbAtomicAdd(volatile BBInt *target, BBInt incr); 00315 00316 // Internal locks // 00317 00318 extern int _bbNeedsLock; 00319 extern bb_mutex_t _bbLock; 00320 00321 #define BB_LOCK if (_bbNeedsLock) { bb_mutex_lock(&_bbLock); } 00322 #define BB_UNLOCK if (_bbNeedsLock) { bb_mutex_unlock(&_bbLock); } 00323 00324 // Deprecated // 00325 00326 #ifndef BB_DISABLE_DEPRECATED 00327 # define BB_THREADREGS BBTHREAD_NUM_REGS 00328 #endif // !BB_DISABLE_DEPRECATED 00329 00330 BB_END_DECLS 00331 00332 #endif // BLITZ_THREAD_H