BlitzMax Extended  0.8.11
Pushing Blitz to the Max.
blitz_thread.h
Go to the documentation of this file.
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