Fix setinfo.
[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         void *thread = (void *)SDL_CreateThread(fn, filename, data);
104 #ifdef THREADDEBUG
105         Sys_PrintfToTerminal("%p thread create %s:%i\n"   , thread, filename, fileline);
106 #endif
107         return thread;
108 }
109
110 int _Thread_WaitThread(void *thread, int retval, const char *filename, int fileline)
111 {
112         int status = retval;
113 #ifdef THREADDEBUG
114         Sys_PrintfToTerminal("%p thread wait %s:%i\n"   , thread, filename, fileline);
115 #endif
116         SDL_WaitThread((SDL_Thread *)thread, &status);
117         return status;
118 }
119
120 // standard barrier implementation using conds and mutexes
121 // see: http://www.howforge.com/implementing-barrier-in-pthreads
122 typedef struct {
123         unsigned int needed;
124         unsigned int called;
125         void *mutex;
126         void *cond;
127 } barrier_t;
128
129 void *_Thread_CreateBarrier(unsigned int count, const char *filename, int fileline)
130 {
131         volatile barrier_t *b = (volatile barrier_t *) Z_Malloc(sizeof(barrier_t));
132 #ifdef THREADDEBUG
133         Sys_PrintfToTerminal("%p barrier create(%d) %s:%i\n", b, count, filename, fileline);
134 #endif
135         b->needed = count;
136         b->called = 0;
137         b->mutex = Thread_CreateMutex();
138         b->cond = Thread_CreateCond();
139         return (void *) b;
140 }
141
142 void _Thread_DestroyBarrier(void *barrier, const char *filename, int fileline)
143 {
144         volatile barrier_t *b = (volatile barrier_t *) barrier;
145 #ifdef THREADDEBUG
146         Sys_PrintfToTerminal("%p barrier destroy %s:%i\n", b, filename, fileline);
147 #endif
148         Thread_DestroyMutex(b->mutex);
149         Thread_DestroyCond(b->cond);
150 }
151
152 void _Thread_WaitBarrier(void *barrier, const char *filename, int fileline)
153 {
154         volatile barrier_t *b = (volatile barrier_t *) barrier;
155 #ifdef THREADDEBUG
156         Sys_PrintfToTerminal("%p barrier wait %s:%i\n", b, filename, fileline);
157 #endif
158         Thread_LockMutex(b->mutex);
159         b->called++;
160         if (b->called == b->needed) {
161                 b->called = 0;
162                 Thread_CondBroadcast(b->cond);
163         } else {
164                 do {
165                         Thread_CondWait(b->cond, b->mutex);
166                 } while(b->called);
167         }
168         Thread_UnlockMutex(b->mutex);
169 }