Mercurial > sdl-ios-xcode
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: */ |