]> git.xonotic.org Git - xonotic/darkplaces.git/blob - thread_win.c
a882f80d00f14d1f7df1deec61a4a82ed08863c3
[xonotic/darkplaces.git] / thread_win.c
1 #include "quakedef.h"
2 #include "thread.h"
3 #include <process.h>
4
5 int Thread_Init(void)
6 {
7         return 0;
8 }
9
10 void Thread_Shutdown(void)
11 {
12 }
13
14 qboolean Thread_HasThreads(void)
15 {
16         return true;
17 }
18
19 void *_Thread_CreateMutex(const char *filename, int fileline)
20 {
21         void *mutex = (void *)CreateMutex(NULL, FALSE, NULL);
22 #ifdef THREADDEBUG
23         printf("%p create %s:%i\n" , mutex, filename, fileline);
24 #endif
25         return mutex;
26 }
27
28 void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
29 {
30 #ifdef THREADDEBUG
31         printf("%p destroy %s:%i\n", mutex, filename, fileline);
32 #endif
33         CloseHandle(mutex);
34 }
35
36 int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
37 {
38 #ifdef THREADDEBUG
39         printf("%p lock %s:%i\n"   , mutex, filename, fileline);
40 #endif
41         return (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) ? -1 : 0;
42 }
43
44 int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
45 {
46 #ifdef THREADDEBUG
47         printf("%p unlock %s:%i\n" , mutex, filename, fileline);
48 #endif
49         return (ReleaseMutex(mutex) == FALSE) ? -1 : 0;
50 }
51
52 typedef struct thread_semaphore_s
53 {
54         HANDLE semaphore;
55         volatile LONG value;
56 }
57 thread_semaphore_t;
58
59 static thread_semaphore_t *Thread_CreateSemaphore(unsigned int v)
60 {
61         thread_semaphore_t *s = (thread_semaphore_t *)calloc(sizeof(*s), 1);
62         s->semaphore = CreateSemaphore(NULL, v, 32768, NULL);
63         s->value = v;
64         return s;
65 }
66
67 static void Thread_DestroySemaphore(thread_semaphore_t *s)
68 {
69         CloseHandle(s->semaphore);
70         free(s);
71 }
72
73 static int Thread_WaitSemaphore(thread_semaphore_t *s, unsigned int msec)
74 {
75         int r = WaitForSingleObject(s->semaphore, msec);
76         if (r == WAIT_OBJECT_0)
77         {
78                 InterlockedDecrement(&s->value);
79                 return 0;
80         }
81         if (r == WAIT_TIMEOUT)
82                 return 1;
83         return -1;
84 }
85
86 static int Thread_PostSemaphore(thread_semaphore_t *s)
87 {
88         InterlockedIncrement(&s->value);
89         if (ReleaseSemaphore(s->semaphore, 1, NULL))
90                 return 0;
91         InterlockedDecrement(&s->value);
92         return -1;
93 }
94
95 typedef struct thread_cond_s
96 {
97         HANDLE mutex;
98         int waiting;
99         int signals;
100         thread_semaphore_t *sem;
101         thread_semaphore_t *done;
102 }
103 thread_cond_t;
104
105 void *Thread_CreateCond(void)
106 {
107         thread_cond_t *c = (thread_cond_t *)calloc(sizeof(*c), 1);
108         c->mutex = CreateMutex(NULL, FALSE, NULL);
109         c->sem = Thread_CreateSemaphore(0);
110         c->done = Thread_CreateSemaphore(0);
111         c->waiting = 0;
112         c->signals = 0;
113         return c;
114 }
115
116 void Thread_DestroyCond(void *cond)
117 {
118         thread_cond_t *c = (thread_cond_t *)cond;
119         Thread_DestroySemaphore(c->sem);
120         Thread_DestroySemaphore(c->done);
121         CloseHandle(c->mutex);
122 }
123
124 int Thread_CondSignal(void *cond)
125 {
126         thread_cond_t *c = (thread_cond_t *)cond;
127         int n;
128         WaitForSingleObject(c->mutex, INFINITE);
129         n = c->waiting - c->signals;
130         if (n > 0)
131         {
132                 c->signals++;
133                 Thread_PostSemaphore(c->sem);
134         }
135         ReleaseMutex(c->mutex);
136         if (n > 0)
137                 Thread_WaitSemaphore(c->done, INFINITE);
138         return 0;
139 }
140
141 int Thread_CondBroadcast(void *cond)
142 {
143         thread_cond_t *c = (thread_cond_t *)cond;
144         int i = 0;
145         int n = 0;
146         WaitForSingleObject(c->mutex, INFINITE);
147         n = c->waiting - c->signals;
148         if (n > 0)
149         {
150                 c->signals += n;
151                 for (i = 0;i < n;i++)
152                         Thread_PostSemaphore(c->sem);
153         }
154         ReleaseMutex(c->mutex);
155         for (i = 0;i < n;i++)
156                 Thread_WaitSemaphore(c->done, INFINITE);
157         return 0;
158 }
159
160 int Thread_CondWait(void *cond, void *mutex)
161 {
162         thread_cond_t *c = (thread_cond_t *)cond;
163         int waitresult;
164
165         WaitForSingleObject(c->mutex, INFINITE);
166         c->waiting++;
167         ReleaseMutex(c->mutex);
168
169         ReleaseMutex(mutex);
170
171         waitresult = Thread_WaitSemaphore(c->sem, INFINITE);
172         WaitForSingleObject(c->mutex, INFINITE);
173         if (c->signals > 0)
174         {
175                 if (waitresult > 0)
176                         Thread_WaitSemaphore(c->sem, INFINITE);
177                 Thread_PostSemaphore(c->done);
178                 c->signals--;
179         }
180         c->waiting--;
181         ReleaseMutex(c->mutex);
182
183         WaitForSingleObject(mutex, INFINITE);
184         return waitresult;
185 }
186
187 typedef struct threadwrapper_s
188 {
189         HANDLE handle;
190         unsigned int threadid;
191         int result;
192         int (*fn)(void *);
193         void *data;
194 }
195 threadwrapper_t;
196
197 unsigned int __stdcall Thread_WrapperFunc(void *d)
198 {
199         threadwrapper_t *w = (threadwrapper_t *)d;
200         w->result = w->fn(w->data);
201         _endthreadex(w->result);
202         return w->result;
203 }
204
205 void *Thread_CreateThread(int (*fn)(void *), void *data)
206 {
207         threadwrapper_t *w = (threadwrapper_t *)calloc(sizeof(*w), 1);
208         w->fn = fn;
209         w->data = data;
210         w->threadid = 0;
211         w->result = 0;
212         w->handle = (HANDLE)_beginthreadex(NULL, 0, Thread_WrapperFunc, (void *)w, 0, &w->threadid);
213         return (void *)w;
214 }
215
216 int Thread_WaitThread(void *d, int retval)
217 {
218         threadwrapper_t *w = (threadwrapper_t *)d;
219         WaitForSingleObject(w->handle, INFINITE);
220         CloseHandle(w->handle);
221         retval = w->result;
222         free(w);
223         return retval;
224 }