8 Con_Printf("Threading disabled in this build\n");
13 void Thread_Shutdown(void)
17 qboolean Thread_HasThreads(void)
26 void *_Thread_CreateMutex(const char *filename, int fileline)
28 void *mutex = (void *)CreateMutex(NULL, FALSE, NULL);
30 Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutex, filename, fileline);
35 void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
38 Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
43 int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
46 Sys_PrintfToTerminal("%p mutex lock %s:%i\n" , mutex, filename, fileline);
48 return (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) ? -1 : 0;
51 int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
54 Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
56 return (ReleaseMutex(mutex) == FALSE) ? -1 : 0;
59 typedef struct thread_semaphore_s
66 static thread_semaphore_t *Thread_CreateSemaphore(unsigned int v)
68 thread_semaphore_t *s = (thread_semaphore_t *)calloc(sizeof(*s), 1);
69 s->semaphore = CreateSemaphore(NULL, v, 32768, NULL);
74 static void Thread_DestroySemaphore(thread_semaphore_t *s)
76 CloseHandle(s->semaphore);
80 static int Thread_WaitSemaphore(thread_semaphore_t *s, unsigned int msec)
82 int r = WaitForSingleObject(s->semaphore, msec);
83 if (r == WAIT_OBJECT_0)
85 InterlockedDecrement(&s->value);
88 if (r == WAIT_TIMEOUT)
93 static int Thread_PostSemaphore(thread_semaphore_t *s)
95 InterlockedIncrement(&s->value);
96 if (ReleaseSemaphore(s->semaphore, 1, NULL))
98 InterlockedDecrement(&s->value);
102 typedef struct thread_cond_s
107 thread_semaphore_t *sem;
108 thread_semaphore_t *done;
112 void *_Thread_CreateCond(const char *filename, int fileline)
114 thread_cond_t *c = (thread_cond_t *)calloc(sizeof(*c), 1);
115 c->mutex = CreateMutex(NULL, FALSE, NULL);
116 c->sem = Thread_CreateSemaphore(0);
117 c->done = Thread_CreateSemaphore(0);
121 Sys_PrintfToTerminal("%p cond create %s:%i\n" , c, filename, fileline);
126 void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
128 thread_cond_t *c = (thread_cond_t *)cond;
130 Sys_PrintfToTerminal("%p cond destroy %s:%i\n" , cond, filename, fileline);
132 Thread_DestroySemaphore(c->sem);
133 Thread_DestroySemaphore(c->done);
134 CloseHandle(c->mutex);
137 int _Thread_CondSignal(void *cond, const char *filename, int fileline)
139 thread_cond_t *c = (thread_cond_t *)cond;
142 Sys_PrintfToTerminal("%p cond signal %s:%i\n" , cond, filename, fileline);
144 WaitForSingleObject(c->mutex, INFINITE);
145 n = c->waiting - c->signals;
149 Thread_PostSemaphore(c->sem);
151 ReleaseMutex(c->mutex);
153 Thread_WaitSemaphore(c->done, INFINITE);
157 int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
159 thread_cond_t *c = (thread_cond_t *)cond;
163 Sys_PrintfToTerminal("%p cond broadcast %s:%i\n" , cond, filename, fileline);
165 WaitForSingleObject(c->mutex, INFINITE);
166 n = c->waiting - c->signals;
170 for (i = 0;i < n;i++)
171 Thread_PostSemaphore(c->sem);
173 ReleaseMutex(c->mutex);
174 for (i = 0;i < n;i++)
175 Thread_WaitSemaphore(c->done, INFINITE);
179 int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
181 thread_cond_t *c = (thread_cond_t *)cond;
184 Sys_PrintfToTerminal("%p cond wait %s:%i\n" , cond, filename, fileline);
187 WaitForSingleObject(c->mutex, INFINITE);
189 ReleaseMutex(c->mutex);
193 waitresult = Thread_WaitSemaphore(c->sem, INFINITE);
194 WaitForSingleObject(c->mutex, INFINITE);
198 Thread_WaitSemaphore(c->sem, INFINITE);
199 Thread_PostSemaphore(c->done);
203 ReleaseMutex(c->mutex);
205 WaitForSingleObject(mutex, INFINITE);
209 typedef struct threadwrapper_s
212 unsigned int threadid;
219 unsigned int __stdcall Thread_WrapperFunc(void *d)
221 threadwrapper_t *w = (threadwrapper_t *)d;
222 w->result = w->fn(w->data);
223 _endthreadex(w->result);
227 void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
229 threadwrapper_t *w = (threadwrapper_t *)calloc(sizeof(*w), 1);
231 Sys_PrintfToTerminal("%p thread create %s:%i\n" , w, filename, fileline);
237 w->handle = (HANDLE)_beginthreadex(NULL, 0, Thread_WrapperFunc, (void *)w, 0, &w->threadid);
241 int _Thread_WaitThread(void *d, int retval, const char *filename, int fileline)
243 threadwrapper_t *w = (threadwrapper_t *)d;
245 Sys_PrintfToTerminal("%p thread wait %s:%i\n" , w, filename, fileline);
247 WaitForSingleObject(w->handle, INFINITE);
248 CloseHandle(w->handle);
254 // standard barrier implementation using conds and mutexes
255 // see: http://www.howforge.com/implementing-barrier-in-pthreads
263 void *_Thread_CreateBarrier(unsigned int count, const char *filename, int fileline)
265 volatile barrier_t *b = (volatile barrier_t *) Z_Malloc(sizeof(barrier_t));
267 Sys_PrintfToTerminal("%p barrier create(%d) %s:%i\n", b, count, filename, fileline);
271 b->mutex = Thread_CreateMutex();
272 b->cond = Thread_CreateCond();
276 void _Thread_DestroyBarrier(void *barrier, const char *filename, int fileline)
278 volatile barrier_t *b = (volatile barrier_t *) barrier;
280 Sys_PrintfToTerminal("%p barrier destroy %s:%i\n", b, filename, fileline);
282 Thread_DestroyMutex(b->mutex);
283 Thread_DestroyCond(b->cond);
286 void _Thread_WaitBarrier(void *barrier, const char *filename, int fileline)
288 volatile barrier_t *b = (volatile barrier_t *) barrier;
290 Sys_PrintfToTerminal("%p barrier wait %s:%i\n", b, filename, fileline);
292 Thread_LockMutex(b->mutex);
294 if (b->called == b->needed) {
296 Thread_CondBroadcast(b->cond);
299 Thread_CondWait(b->cond, b->mutex);
302 Thread_UnlockMutex(b->mutex);