BlitzMax Extended  0.8.19
Pushing Blitz to the Max.
blitz_thread.h
Go to the documentation of this file.
1 
7 #ifndef BLITZ_THREAD_H
8 #define BLITZ_THREAD_H
9 
10 #include "_common.h"
11 
12 #ifdef BB_OS_LINUX
13 # include <semaphore.h>
14 #endif
15 
16 #ifdef BB_OS_MACOS
17 # include <mach/semaphore.h>
18 # include <mach/task.h>
19 # include <mach/mach_init.h>
20 
21 # include <libkern/OSAtomic.h> // test
22 #endif
23 
24 #ifndef BB_OS_WIN32
25 # include <pthread.h>
26 # include <unistd.h>
27 # include <signal.h>
28 #endif // !BB_OS_WIN32
29 
30 BB_BEGIN_DECLS
31 
32 #ifdef BB_OS_LINUX
33 typedef pthread_mutex_t bb_mutex_t;
34 typedef sem_t bb_sem_t;
35 #endif
36 
37 #ifdef BB_OS_MACOS
38 typedef pthread_mutex_t bb_mutex_t;
39 typedef semaphore_t bb_sem_t;
40 #endif
41 
42 #ifdef BB_OS_WIN32
43 typedef CRITICAL_SECTION bb_mutex_t;
44 typedef HANDLE bb_sem_t;
45 #endif
46 
47 #ifndef BB_OS_WIN32
48 extern pthread_mutexattr_t _bb_mutexattr;
49 #endif // !BB_OS_WIN32
50 
51 // Replacing macros with actual inline functions
52 #ifdef BB_ENABLE_EXPERIMENTAL
53 
54 inline bool bb_mutex_init(bb_mutex_t *mutex)
55 {
56 #ifdef BB_OS_WIN32
57  InitializeCriticalSection(mutex);
58  return true;
59 #else
60  return pthread_mutex_init(mutex, &_bb_mutexattr) >= 0;
61 #endif
62 }
63 
64 inline bool bb_mutex_destroy(bb_mutex_t *mutex)
65 {
66 #ifdef BB_OS_WIN32
67  DeleteCriticalSection(mutex);
68  return true;
69 #else
70  return pthread_mutex_destroy(mutex) >= 0;
71 #endif
72 }
73 
74 inline bool bb_mutex_lock(bb_mutex_t *mutex)
75 {
76 #ifdef BB_OS_WIN32
77  DeleteCriticalSection(mutex);
78  return true;
79 #else
80  return pthread_mutex_lock(mutex) >= 0;
81 #endif
82 }
83 
84 inline bool bb_mutex_unlock(bb_mutex_t *mutex)
85 {
86 #ifdef BB_OS_WIN32
87  LeaveCriticalSection(mutex);
88  return true;
89 #else
90  return pthread_mutex_lock(mutex) >= 0;
91 #endif
92 }
93 
94 inline bool bb_mutex_trylock(bb_mutex_t *mutex)
95 {
96 #ifdef BB_OS_WIN32
97  return TryEnterCriticalSection(mutex) != 0;
98 #else
99  return pthread_mutex_trylock(mutex) == 0;
100 #endif
101 }
102 
103 
104 
105 inline bool bb_sem_init(bb_sem_t *sem, size_t count)
106 {
107 #if defined (BB_OS_LINUX)
108  return sem_init(sem, 0, count) >= 0;
109 #elif defined (BB_OS_MACOS)
110  return semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, count) >= 0;
111 #elif defined (BB_OS_WIN32)
112  *sem = CreateSemaphore(0, count, 0x7fffffff, 0);
113  return *sem != 0;
114 #endif
115 }
116 
117 inline bool bb_sem_destroy(bb_sem_t *sem)
118 {
119 #if defined (BB_OS_LINUX)
120  return sem_destroy(sem);
121 #elif defined (BB_OS_MACOS)
122  return semaphore_destroy(mach_task_self(), *sem);
123 #elif defined (BB_OS_WIN32)
124  CloseHandle(*sem);
125 #endif
126 }
127 
128 inline bool bb_sem_wait(bb_sem_t *sem)
129 {
130 #if defined (BB_OS_LINUX)
131  return sem_wait(sem);
132 #elif defined (BB_OS_MACOS)
133  return semaphore_wait(*sem);
134 #elif defined (BB_OS_WIN32)
135  return WaitForSingleObject(*sem, INFINITE);
136 #endif
137 }
138 
139 inline bool bb_sem_post(bb_sem_t *sem)
140 {
141 #if defined (BB_OS_LINUX)
142  return sem_post(sem);
143 #elif defined (BB_OS_MACOS)
144  return semaphore_signal(*sem);
145 #elif defined (BB_OS_WIN32)
146  return ReleaseSemaphore(*sem, 1, 0);
147 #endif
148 }
149 
150 #else // BB_ENABLE_EXPERIMENTAL
151 
152 #ifdef BB_OS_WIN32
153 
154 # define bb_mutex_init(MUTPTR) (InitializeCriticalSection(MUTPTR), 1)
155 # define bb_mutex_destroy(MUTPTR) DeleteCriticalSection(MUTPTR)
156 # define bb_mutex_lock(MUTPTR) EnterCriticalSection(MUTPTR)
157 # define bb_mutex_unlock(MUTPTR) LeaveCriticalSection(MUTPTR)
158 # define bb_mutex_trylock(MUTPTR) (TryEnterCriticalSection(MUTPTR) != 0)
159 
160 # define bb_sem_init(SEMPTR,COUNT) ((*(SEMPTR) = CreateSemaphore(0, (COUNT), 0x7fffffff, 0)) != 0)
161 # define bb_sem_destroy(SEMPTR) CloseHandle(*(SEMPTR))
162 # define bb_sem_wait(SEMPTR) WaitForSingleObject(*(SEMPTR), INFINITE)
163 # define bb_sem_post(SEMPTR) ReleaseSemaphore(*(SEMPTR), 1, 0)
164 
165 #else // BB_OS_WIN32
166 
167 extern pthread_mutexattr_t _bb_mutexattr;
168 
169 # define bb_mutex_init(MUTPTR) (pthread_mutex_init((MUTPTR),&_bb_mutexattr) >= 0)
170 # define bb_mutex_destroy(MUTPTR) pthread_mutex_destroy(MUTPTR)
171 # define bb_mutex_lock(MUTPTR) pthread_mutex_lock(MUTPTR)
172 # define bb_mutex_unlock(MUTPTR) pthread_mutex_unlock(MUTPTR)
173 # define bb_mutex_trylock(MUTPTR) (pthread_mutex_trylock(MUTPTR) == 0)
174 
175 #endif // !BB_OS_WIN32
176 
177 #ifdef BB_OS_MACOS
178 # define bb_sem_init(SEMPTR,COUNT) (semaphore_create(mach_task_self(), (SEMPTR), SYNC_POLICY_FIFO, (COUNT)) >= 0)
179 # define bb_sem_destroy(SEMPTR) semaphore_destroy(mach_task_self(), *(SEMPTR))
180 # define bb_sem_wait(SEMPTR) semaphore_wait(*(SEMPTR))
181 # define bb_sem_post(SEMPTR) semaphore_signal(*(SEMPTR))
182 #endif // BB_OS_MACOS
183 
184 #ifdef BB_OS_LINUX
185 # define bb_sem_init(SEMPTR, COUNT) (sem_init((SEMPTR), 0, (COUNT)) >= 0)
186 # define bb_sem_destroy sem_destroy
187 # define bb_sem_wait sem_wait
188 # define bb_sem_post sem_post
189 #endif // BB_OS_LINUX
190 
191 #endif // !BB_ENABLE_EXPERIMENTAL
192 
193 #ifdef BB_OS_WIN32
194 # define BBTHREAD_NUM_REGS 7
195 #elif BB_CPU_PPC
196 # define BBTHREAD_NUM_REGS 19
197 #else
198 # define BBTHREAD_NUM_REGS 4
199 #endif
200 
205 typedef BBObject *(*BBThreadProc)(BBObject*);
206 
207 typedef struct BBThread BBThread;
208 
209 #define BBTHREAD_DATA_SIZE 32
210 
214 struct BBThread
215 {
216  BBThread *succ;
217  BBThreadProc proc;
218  void *data[BBTHREAD_DATA_SIZE];
219  int detached;
220  void *stackTop;
221  void *locked_sp;
222  int locked_regs[BBTHREAD_NUM_REGS];
223 #ifdef BB_OS_WIN32
224  HANDLE handle;
225  DWORD id;
226 #else
227  pthread_t handle;
228  int suspended;
229  bb_sem_t runsema;
230  bb_sem_t acksema;
231 #endif // !BB_OS_WIN32
232 };
233 
234 // Sets up the threading environment
235 // Automatically called by bbStartup (blitz_app.c)
236 void bbThreadStartup();
237 
244 BBThread* bbThreadCreate(BBThreadProc entry, BBObject *data);
245 
249 void bbThreadDetach(BBThread *thread);
250 
254 BBObject* bbThreadWait(BBThread *thread);
255 
260 BBThread* bbThreadGetMain();
261 
269 BBThread* bbThreadGetCurrent();
270 
274 BBInt bbThreadSuspend(BBThread *thread);
275 
279 BBInt bbThreadResume(BBThread *thread);
280 
281 
282 
286 BBInt bbThreadAllocData();
287 
291 void bbThreadSetData(BBInt index, BBObject *data);
292 
296 BBObject* bbThreadGetData(BBInt index);
297 
298 // These MUST be inside a BB_LOCK/BB_UNLOCK
299 BBThread* _bbThreadLockThreads();
300 void _bbThreadUnlockThreads();
301 
305 BBInt bbAtomicCAS(volatile BBInt *target, BBInt old_value, BBInt new_value);
306 
313 BBInt bbAtomicAdd(volatile BBInt *target, BBInt incr);
314 
315 // Internal locks //
316 
317 extern int _bbNeedsLock;
318 extern bb_mutex_t _bbLock;
319 
320 #define BB_LOCK if (_bbNeedsLock) { bb_mutex_lock(&_bbLock); }
321 #define BB_UNLOCK if (_bbNeedsLock) { bb_mutex_unlock(&_bbLock); }
322 
323 // Deprecated //
324 
325 #ifndef BB_DISABLE_DEPRECATED
326 # define BB_THREADREGS BBTHREAD_NUM_REGS
327 #endif // !BB_DISABLE_DEPRECATED
328 
329 BB_END_DECLS
330 
331 #endif // BLITZ_THREAD_H