comparison src/thread/SDL_thread.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents 290b5baf2fca
children 4436464c4f51
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
36 static int SDL_maxthreads = 0; 36 static int SDL_maxthreads = 0;
37 static int SDL_numthreads = 0; 37 static int SDL_numthreads = 0;
38 static SDL_Thread **SDL_Threads = NULL; 38 static SDL_Thread **SDL_Threads = NULL;
39 static SDL_mutex *thread_lock = NULL; 39 static SDL_mutex *thread_lock = NULL;
40 40
41 int SDL_ThreadsInit(void) 41 int
42 { 42 SDL_ThreadsInit(void)
43 int retval; 43 {
44 44 int retval;
45 retval = 0; 45
46 thread_lock = SDL_CreateMutex(); 46 retval = 0;
47 if ( thread_lock == NULL ) { 47 thread_lock = SDL_CreateMutex();
48 retval = -1; 48 if (thread_lock == NULL) {
49 } 49 retval = -1;
50 return(retval); 50 }
51 return (retval);
51 } 52 }
52 53
53 /* This should never be called... 54 /* This should never be called...
54 If this is called by SDL_Quit(), we don't know whether or not we should 55 If this is called by SDL_Quit(), we don't know whether or not we should
55 clean up threads here. If any threads are still running after this call, 56 clean up threads here. If any threads are still running after this call,
56 they will no longer have access to any per-thread data. 57 they will no longer have access to any per-thread data.
57 */ 58 */
58 void SDL_ThreadsQuit(void) 59 void
59 { 60 SDL_ThreadsQuit(void)
60 SDL_mutex *mutex; 61 {
61 62 SDL_mutex *mutex;
62 mutex = thread_lock; 63
63 thread_lock = NULL; 64 mutex = thread_lock;
64 if ( mutex != NULL ) { 65 thread_lock = NULL;
65 SDL_DestroyMutex(mutex); 66 if (mutex != NULL) {
66 } 67 SDL_DestroyMutex(mutex);
68 }
67 } 69 }
68 70
69 /* Routines for manipulating the thread list */ 71 /* Routines for manipulating the thread list */
70 static void SDL_AddThread(SDL_Thread *thread) 72 static void
71 { 73 SDL_AddThread(SDL_Thread * thread)
72 /* WARNING: 74 {
73 If the very first threads are created simultaneously, then 75 /* WARNING:
74 there could be a race condition causing memory corruption. 76 If the very first threads are created simultaneously, then
75 In practice, this isn't a problem because by definition there 77 there could be a race condition causing memory corruption.
76 is only one thread running the first time this is called. 78 In practice, this isn't a problem because by definition there
77 */ 79 is only one thread running the first time this is called.
78 if ( !thread_lock ) { 80 */
79 if ( SDL_ThreadsInit() < 0 ) { 81 if (!thread_lock) {
80 return; 82 if (SDL_ThreadsInit() < 0) {
81 } 83 return;
82 } 84 }
83 SDL_mutexP(thread_lock); 85 }
84 86 SDL_mutexP(thread_lock);
85 /* Expand the list of threads, if necessary */ 87
88 /* Expand the list of threads, if necessary */
86 #ifdef DEBUG_THREADS 89 #ifdef DEBUG_THREADS
87 printf("Adding thread (%d already - %d max)\n", 90 printf("Adding thread (%d already - %d max)\n",
88 SDL_numthreads, SDL_maxthreads); 91 SDL_numthreads, SDL_maxthreads);
89 #endif 92 #endif
90 if ( SDL_numthreads == SDL_maxthreads ) { 93 if (SDL_numthreads == SDL_maxthreads) {
91 SDL_Thread **threads; 94 SDL_Thread **threads;
92 threads = (SDL_Thread **)SDL_realloc(SDL_Threads, 95 threads = (SDL_Thread **) SDL_realloc(SDL_Threads,
93 (SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads)); 96 (SDL_maxthreads +
94 if ( threads == NULL ) { 97 ARRAY_CHUNKSIZE) *
95 SDL_OutOfMemory(); 98 (sizeof *threads));
96 goto done; 99 if (threads == NULL) {
97 } 100 SDL_OutOfMemory();
98 SDL_maxthreads += ARRAY_CHUNKSIZE; 101 goto done;
99 SDL_Threads = threads; 102 }
100 } 103 SDL_maxthreads += ARRAY_CHUNKSIZE;
101 SDL_Threads[SDL_numthreads++] = thread; 104 SDL_Threads = threads;
102 done: 105 }
103 SDL_mutexV(thread_lock); 106 SDL_Threads[SDL_numthreads++] = thread;
104 } 107 done:
105 108 SDL_mutexV(thread_lock);
106 static void SDL_DelThread(SDL_Thread *thread) 109 }
107 { 110
108 int i; 111 static void
109 112 SDL_DelThread(SDL_Thread * thread)
110 if ( !thread_lock ) { 113 {
111 return; 114 int i;
112 } 115
113 SDL_mutexP(thread_lock); 116 if (!thread_lock) {
114 for ( i=0; i<SDL_numthreads; ++i ) { 117 return;
115 if ( thread == SDL_Threads[i] ) { 118 }
116 break; 119 SDL_mutexP(thread_lock);
117 } 120 for (i = 0; i < SDL_numthreads; ++i) {
118 } 121 if (thread == SDL_Threads[i]) {
119 if ( i < SDL_numthreads ) { 122 break;
120 if ( --SDL_numthreads > 0 ) { 123 }
121 while ( i < SDL_numthreads ) { 124 }
122 SDL_Threads[i] = SDL_Threads[i+1]; 125 if (i < SDL_numthreads) {
123 ++i; 126 if (--SDL_numthreads > 0) {
124 } 127 while (i < SDL_numthreads) {
125 } else { 128 SDL_Threads[i] = SDL_Threads[i + 1];
126 SDL_maxthreads = 0; 129 ++i;
127 SDL_free(SDL_Threads); 130 }
128 SDL_Threads = NULL; 131 } else {
129 } 132 SDL_maxthreads = 0;
133 SDL_free(SDL_Threads);
134 SDL_Threads = NULL;
135 }
130 #ifdef DEBUG_THREADS 136 #ifdef DEBUG_THREADS
131 printf("Deleting thread (%d left - %d max)\n", 137 printf("Deleting thread (%d left - %d max)\n",
132 SDL_numthreads, SDL_maxthreads); 138 SDL_numthreads, SDL_maxthreads);
133 #endif 139 #endif
134 } 140 }
135 SDL_mutexV(thread_lock); 141 SDL_mutexV(thread_lock);
136 142
137 if ( SDL_Threads == NULL ) { 143 if (SDL_Threads == NULL) {
138 SDL_ThreadsQuit(); 144 SDL_ThreadsQuit();
139 } 145 }
140 } 146 }
141 147
142 /* The default (non-thread-safe) global error variable */ 148 /* The default (non-thread-safe) global error variable */
143 static SDL_error SDL_global_error; 149 static SDL_error SDL_global_error;
144 150
145 /* Routine to get the thread-specific error variable */ 151 /* Routine to get the thread-specific error variable */
146 SDL_error *SDL_GetErrBuf(void) 152 SDL_error *
147 { 153 SDL_GetErrBuf(void)
148 SDL_error *errbuf; 154 {
149 155 SDL_error *errbuf;
150 errbuf = &SDL_global_error; 156
151 if ( SDL_Threads ) { 157 errbuf = &SDL_global_error;
152 int i; 158 if (SDL_Threads) {
153 Uint32 this_thread; 159 int i;
154 160 Uint32 this_thread;
155 this_thread = SDL_ThreadID(); 161
156 SDL_mutexP(thread_lock); 162 this_thread = SDL_ThreadID();
157 for ( i=0; i<SDL_numthreads; ++i ) { 163 SDL_mutexP(thread_lock);
158 if ( this_thread == SDL_Threads[i]->threadid ) { 164 for (i = 0; i < SDL_numthreads; ++i) {
159 errbuf = &SDL_Threads[i]->errbuf; 165 if (this_thread == SDL_Threads[i]->threadid) {
160 break; 166 errbuf = &SDL_Threads[i]->errbuf;
161 } 167 break;
162 } 168 }
163 SDL_mutexV(thread_lock); 169 }
164 } 170 SDL_mutexV(thread_lock);
165 return(errbuf); 171 }
172 return (errbuf);
166 } 173 }
167 174
168 175
169 /* Arguments and callback to setup and run the user thread function */ 176 /* Arguments and callback to setup and run the user thread function */
170 typedef struct { 177 typedef struct
171 int (SDLCALL *func)(void *); 178 {
172 void *data; 179 int (SDLCALL * func) (void *);
173 SDL_Thread *info; 180 void *data;
174 SDL_sem *wait; 181 SDL_Thread *info;
182 SDL_sem *wait;
175 } thread_args; 183 } thread_args;
176 184
177 void SDL_RunThread(void *data) 185 void
178 { 186 SDL_RunThread(void *data)
179 thread_args *args; 187 {
180 int (SDLCALL *userfunc)(void *); 188 thread_args *args;
181 void *userdata; 189 int (SDLCALL * userfunc) (void *);
182 int *statusloc; 190 void *userdata;
183 191 int *statusloc;
184 /* Perform any system-dependent setup 192
185 - this function cannot fail, and cannot use SDL_SetError() 193 /* Perform any system-dependent setup
186 */ 194 - this function cannot fail, and cannot use SDL_SetError()
187 SDL_SYS_SetupThread(); 195 */
188 196 SDL_SYS_SetupThread();
189 /* Get the thread id */ 197
190 args = (thread_args *)data; 198 /* Get the thread id */
191 args->info->threadid = SDL_ThreadID(); 199 args = (thread_args *) data;
192 200 args->info->threadid = SDL_ThreadID();
193 /* Figure out what function to run */ 201
194 userfunc = args->func; 202 /* Figure out what function to run */
195 userdata = args->data; 203 userfunc = args->func;
196 statusloc = &args->info->status; 204 userdata = args->data;
197 205 statusloc = &args->info->status;
198 /* Wake up the parent thread */ 206
199 SDL_SemPost(args->wait); 207 /* Wake up the parent thread */
200 208 SDL_SemPost(args->wait);
201 /* Run the function */ 209
202 *statusloc = userfunc(userdata); 210 /* Run the function */
211 *statusloc = userfunc(userdata);
203 } 212 }
204 213
205 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD 214 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
206 #undef SDL_CreateThread 215 #undef SDL_CreateThread
207 DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) 216 DECLSPEC SDL_Thread *SDLCALL
217 SDL_CreateThread(int (SDLCALL * fn) (void *), void *data,
218 pfnSDL_CurrentBeginThread pfnBeginThread,
219 pfnSDL_CurrentEndThread pfnEndThread)
208 #else 220 #else
209 DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data) 221 DECLSPEC SDL_Thread *SDLCALL
222 SDL_CreateThread(int (SDLCALL * fn) (void *), void *data)
210 #endif 223 #endif
211 { 224 {
212 SDL_Thread *thread; 225 SDL_Thread *thread;
213 thread_args *args; 226 thread_args *args;
214 int ret; 227 int ret;
215 228
216 /* Allocate memory for the thread info structure */ 229 /* Allocate memory for the thread info structure */
217 thread = (SDL_Thread *)SDL_malloc(sizeof(*thread)); 230 thread = (SDL_Thread *) SDL_malloc(sizeof(*thread));
218 if ( thread == NULL ) { 231 if (thread == NULL) {
219 SDL_OutOfMemory(); 232 SDL_OutOfMemory();
220 return(NULL); 233 return (NULL);
221 } 234 }
222 SDL_memset(thread, 0, (sizeof *thread)); 235 SDL_memset(thread, 0, (sizeof *thread));
223 thread->status = -1; 236 thread->status = -1;
224 237
225 /* Set up the arguments for the thread */ 238 /* Set up the arguments for the thread */
226 args = (thread_args *)SDL_malloc(sizeof(*args)); 239 args = (thread_args *) SDL_malloc(sizeof(*args));
227 if ( args == NULL ) { 240 if (args == NULL) {
228 SDL_OutOfMemory(); 241 SDL_OutOfMemory();
229 SDL_free(thread); 242 SDL_free(thread);
230 return(NULL); 243 return (NULL);
231 } 244 }
232 args->func = fn; 245 args->func = fn;
233 args->data = data; 246 args->data = data;
234 args->info = thread; 247 args->info = thread;
235 args->wait = SDL_CreateSemaphore(0); 248 args->wait = SDL_CreateSemaphore(0);
236 if ( args->wait == NULL ) { 249 if (args->wait == NULL) {
237 SDL_free(thread); 250 SDL_free(thread);
238 SDL_free(args); 251 SDL_free(args);
239 return(NULL); 252 return (NULL);
240 } 253 }
241 254
242 /* Add the thread to the list of available threads */ 255 /* Add the thread to the list of available threads */
243 SDL_AddThread(thread); 256 SDL_AddThread(thread);
244 257
245 /* Create the thread and go! */ 258 /* Create the thread and go! */
246 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD 259 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
247 ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread); 260 ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
248 #else 261 #else
249 ret = SDL_SYS_CreateThread(thread, args); 262 ret = SDL_SYS_CreateThread(thread, args);
250 #endif 263 #endif
251 if ( ret >= 0 ) { 264 if (ret >= 0) {
252 /* Wait for the thread function to use arguments */ 265 /* Wait for the thread function to use arguments */
253 SDL_SemWait(args->wait); 266 SDL_SemWait(args->wait);
254 } else { 267 } else {
255 /* Oops, failed. Gotta free everything */ 268 /* Oops, failed. Gotta free everything */
256 SDL_DelThread(thread); 269 SDL_DelThread(thread);
257 SDL_free(thread); 270 SDL_free(thread);
258 thread = NULL; 271 thread = NULL;
259 } 272 }
260 SDL_DestroySemaphore(args->wait); 273 SDL_DestroySemaphore(args->wait);
261 SDL_free(args); 274 SDL_free(args);
262 275
263 /* Everything is running now */ 276 /* Everything is running now */
264 return(thread); 277 return (thread);
265 } 278 }
266 279
267 void SDL_WaitThread(SDL_Thread *thread, int *status) 280 void
268 { 281 SDL_WaitThread(SDL_Thread * thread, int *status)
269 if ( thread ) { 282 {
270 SDL_SYS_WaitThread(thread); 283 if (thread) {
271 if ( status ) { 284 SDL_SYS_WaitThread(thread);
272 *status = thread->status; 285 if (status) {
273 } 286 *status = thread->status;
274 SDL_DelThread(thread); 287 }
275 SDL_free(thread); 288 SDL_DelThread(thread);
276 } 289 SDL_free(thread);
277 } 290 }
278 291 }
279 Uint32 SDL_GetThreadID(SDL_Thread *thread) 292
280 { 293 Uint32
281 Uint32 id; 294 SDL_GetThreadID(SDL_Thread * thread)
282 295 {
283 if ( thread ) { 296 Uint32 id;
284 id = thread->threadid; 297
285 } else { 298 if (thread) {
286 id = SDL_ThreadID(); 299 id = thread->threadid;
287 } 300 } else {
288 return(id); 301 id = SDL_ThreadID();
289 } 302 }
290 303 return (id);
291 void SDL_KillThread(SDL_Thread *thread) 304 }
292 { 305
293 if ( thread ) { 306 void
294 SDL_SYS_KillThread(thread); 307 SDL_KillThread(SDL_Thread * thread)
295 SDL_WaitThread(thread, NULL); 308 {
296 } 309 if (thread) {
297 } 310 SDL_SYS_KillThread(thread);
298 311 SDL_WaitThread(thread, NULL);
312 }
313 }
314
315 /* vi: set ts=4 sw=4 expandtab: */