we need to #include <SDL.h> before #include "quakedef.h"
[xonotic/darkplaces.git] / thread_sdl.c
1 #include <SDL.h>
2 #include <SDL_thread.h>
3 #include "quakedef.h"
4 #include "thread.h"
5
6 int Thread_Init(void)
7 {
8 #ifdef THREADDISABLE
9         Con_Printf("Threading disabled in this build\n");
10 #endif
11         return 0;
12 }
13
14 void Thread_Shutdown(void)
15 {
16 }
17
18 qboolean Thread_HasThreads(void)
19 {
20 #ifdef THREADDISABLE
21         return false;
22 #else
23         return true;
24 #endif
25 }
26
27 void *_Thread_CreateMutex(const char *filename, int fileline)
28 {
29         void *mutex = SDL_CreateMutex();
30 #ifdef THREADDEBUG
31         Sys_PrintfToTerminal("%p mutex create %s:%i\n" , mutex, filename, fileline);
32 #endif
33         return mutex;
34 }
35
36 void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
37 {
38 #ifdef THREADDEBUG
39         Sys_PrintfToTerminal("%p mutex destroy %s:%i\n", mutex, filename, fileline);
40 #endif
41         SDL_DestroyMutex((SDL_mutex *)mutex);
42 }
43
44 int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
45 {
46 #ifdef THREADDEBUG
47         Sys_PrintfToTerminal("%p mutex lock %s:%i\n"   , mutex, filename, fileline);
48 #endif
49         return SDL_LockMutex((SDL_mutex *)mutex);
50 }
51
52 int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
53 {
54 #ifdef THREADDEBUG
55         Sys_PrintfToTerminal("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
56 #endif
57         return SDL_UnlockMutex((SDL_mutex *)mutex);
58 }
59
60 void *_Thread_CreateCond(const char *filename, int fileline)
61 {
62         void *cond = (void *)SDL_CreateCond();
63 #ifdef THREADDEBUG
64         Sys_PrintfToTerminal("%p cond create %s:%i\n"   , cond, filename, fileline);
65 #endif
66         return cond;
67 }
68
69 void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
70 {
71 #ifdef THREADDEBUG
72         Sys_PrintfToTerminal("%p cond destroy %s:%i\n"   , cond, filename, fileline);
73 #endif
74         SDL_DestroyCond((SDL_cond *)cond);
75 }
76
77 int _Thread_CondSignal(void *cond, const char *filename, int fileline)
78 {
79 #ifdef THREADDEBUG
80         Sys_PrintfToTerminal("%p cond signal %s:%i\n"   , cond, filename, fileline);
81 #endif
82         return SDL_CondSignal((SDL_cond *)cond);
83 }
84
85 int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
86 {
87 #ifdef THREADDEBUG
88         Sys_PrintfToTerminal("%p cond broadcast %s:%i\n"   , cond, filename, fileline);
89 #endif
90         return SDL_CondBroadcast((SDL_cond *)cond);
91 }
92
93 int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
94 {
95 #ifdef THREADDEBUG
96         Sys_PrintfToTerminal("%p cond wait %s:%i\n"   , cond, filename, fileline);
97 #endif
98         return SDL_CondWait((SDL_cond *)cond, (SDL_mutex *)mutex);
99 }
100
101 void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
102 {
103 #if SDL_MAJOR_VERSION == 1
104         void *thread = (void *)SDL_CreateThread(fn, data);
105 #else
106         void *thread = (void *)SDL_CreateThread(fn, filename, data);
107 #endif
108 #ifdef THREADDEBUG
109         Sys_PrintfToTerminal("%p thread create %s:%i\n"   , thread, filename, fileline);
110 #endif
111         return thread;
112 }
113
114 int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
115 {
116         int status = retval;
117 #ifdef THREADDEBUG
118         Sys_PrintfToTerminal("%p thread wait %s:%i\n"   , thread, filename, fileline);
119 #endif
120         SDL_WaitThread((SDL_Thread *)thread, &status);
121         return status;
122 }
123
124 // standard barrier implementation using conds and mutexes
125 // see: http://www.howforge.com/implementing-barrier-in-pthreads
126 typedef struct {
127         unsigned int needed;
128         unsigned int called;
129         void *mutex;
130         void *cond;
131 } barrier_t;
132
133 void *_Thread_CreateBarrier(unsigned int count, const char *filename, int fileline)
134 {
135         volatile barrier_t *b = (volatile barrier_t *) Z_Malloc(sizeof(barrier_t));
136 #ifdef THREADDEBUG
137         Sys_PrintfToTerminal("%p barrier create(%d) %s:%i\n", b, count, filename, fileline);
138 #endif
139         b->needed = count;
140         b->called = 0;
141         b->mutex = Thread_CreateMutex();
142         b->cond = Thread_CreateCond();
143         return (void *) b;
144 }
145
146 void _Thread_DestroyBarrier(void *barrier, const char *filename, int fileline)
147 {
148         volatile barrier_t *b = (volatile barrier_t *) barrier;
149 #ifdef THREADDEBUG
150         Sys_PrintfToTerminal("%p barrier destroy %s:%i\n", b, filename, fileline);
151 #endif
152         Thread_DestroyMutex(b->mutex);
153         Thread_DestroyCond(b->cond);
154 }
155
156 void _Thread_WaitBarrier(void *barrier, const char *filename, int fileline)
157 {
158         volatile barrier_t *b = (volatile barrier_t *) barrier;
159 #ifdef THREADDEBUG
160         Sys_PrintfToTerminal("%p barrier wait %s:%i\n", b, filename, fileline);
161 #endif
162         Thread_LockMutex(b->mutex);
163         b->called++;
164         if (b->called == b->needed) {
165                 b->called = 0;
166                 Thread_CondBroadcast(b->cond);
167         } else {
168                 do {
169                         Thread_CondWait(b->cond, b->mutex);
170                 } while(b->called);
171         }
172         Thread_UnlockMutex(b->mutex);
173 }