SDL_thread.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:7k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_thread.c,v 1.4 2002/04/22 21:38:02 wmay Exp $";
  21. #endif
  22. /* System independent thread management routines for SDL */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include "SDL_error.h"
  27. #include "SDL_mutex.h"
  28. #include "SDL_thread.h"
  29. #include "SDL_thread_c.h"
  30. #include "SDL_systhread.h"
  31. #define ARRAY_CHUNKSIZE 32
  32. /* The array of threads currently active in the application
  33.    (except the main thread)
  34.    The manipulation of an array here is safer than using a linked list.
  35. */
  36. static int SDL_maxthreads = 0;
  37. static int SDL_numthreads = 0;
  38. static SDL_Thread **SDL_Threads = NULL;
  39. static struct SignalSemaphore thread_lock;
  40. int thread_lock_created = 0;
  41. int SDL_ThreadsInit(void)
  42. {
  43. InitSemaphore(&thread_lock);
  44. thread_lock_created=1;
  45. return 0;
  46. }
  47. /* This should never be called...
  48.    If this is called by SDL_Quit(), we don't know whether or not we should
  49.    clean up threads here.  If any threads are still running after this call,
  50.    they will no longer have access to any per-thread data.
  51.  */
  52. void SDL_ThreadsQuit()
  53. {
  54. thread_lock_created=0;
  55. }
  56. /* Routines for manipulating the thread list */
  57. static void SDL_AddThread(SDL_Thread *thread)
  58. {
  59. SDL_Thread **threads;
  60. /* WARNING:
  61.    If the very first threads are created simultaneously, then
  62.    there could be a race condition causing memory corruption.
  63.    In practice, this isn't a problem because by definition there
  64.    is only one thread running the first time this is called.
  65. */
  66. if ( !thread_lock_created ) {
  67. if ( SDL_ThreadsInit() < 0 ) {
  68. return;
  69. }
  70. }
  71. ObtainSemaphore(&thread_lock);
  72. /* Expand the list of threads, if necessary */
  73. #ifdef DEBUG_THREADS
  74. printf("Adding thread (%d already - %d max)n",
  75. SDL_numthreads, SDL_maxthreads);
  76. #endif
  77. if ( SDL_numthreads == SDL_maxthreads ) {
  78. threads=(SDL_Thread **)malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)*
  79.                               (sizeof *threads));
  80. if ( threads == NULL ) {
  81. SDL_OutOfMemory();
  82. goto done;
  83. }
  84. memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads));
  85. SDL_maxthreads += ARRAY_CHUNKSIZE;
  86. if ( SDL_Threads ) {
  87. free(SDL_Threads);
  88. }
  89. SDL_Threads = threads;
  90. }
  91. SDL_Threads[SDL_numthreads++] = thread;
  92. done:
  93. ReleaseSemaphore(&thread_lock);
  94. }
  95. static void SDL_DelThread(SDL_Thread *thread)
  96. {
  97. int i;
  98. if ( thread_lock_created ) {
  99. ObtainSemaphore(&thread_lock);
  100. for ( i=0; i<SDL_numthreads; ++i ) {
  101. if ( thread == SDL_Threads[i] ) {
  102. break;
  103. }
  104. }
  105. if ( i < SDL_numthreads ) {
  106. --SDL_numthreads;
  107. while ( i < SDL_numthreads ) {
  108. SDL_Threads[i] = SDL_Threads[i+1];
  109. ++i;
  110. }
  111. #ifdef DEBUG_THREADS
  112. printf("Deleting thread (%d left - %d max)n",
  113. SDL_numthreads, SDL_maxthreads);
  114. #endif
  115. }
  116. ReleaseSemaphore(&thread_lock);
  117. }
  118. }
  119. /* The default (non-thread-safe) global error variable */
  120. static SDL_error SDL_global_error;
  121. /* Routine to get the thread-specific error variable */
  122. SDL_error *SDL_GetErrBuf(void)
  123. {
  124. SDL_error *errbuf;
  125. errbuf = &SDL_global_error;
  126. if ( SDL_Threads ) {
  127. int i;
  128. Uint32 this_thread;
  129. this_thread = SDL_ThreadID();
  130. ObtainSemaphore(&thread_lock);
  131. for ( i=0; i<SDL_numthreads; ++i ) {
  132. if ( this_thread == SDL_Threads[i]->threadid ) {
  133. errbuf = &SDL_Threads[i]->errbuf;
  134. break;
  135. }
  136. }
  137. ReleaseSemaphore(&thread_lock);
  138. }
  139. return(errbuf);
  140. }
  141. /* Arguments and callback to setup and run the user thread function */
  142. typedef struct {
  143. int (*func)(void *);
  144. void *data;
  145. SDL_Thread *info;
  146. struct Task *wait;
  147. } thread_args;
  148. void SDL_RunThread(void *data)
  149. {
  150. thread_args *args;
  151. int (*userfunc)(void *);
  152. void *userdata;
  153. int *statusloc;
  154. /* Perform any system-dependent setup
  155.    - this function cannot fail, and cannot use SDL_SetError()
  156.  */
  157. SDL_SYS_SetupThread();
  158. /* Get the thread id */
  159. args = (thread_args *)data;
  160. args->info->threadid = SDL_ThreadID();
  161. /* Figure out what function to run */
  162. userfunc = args->func;
  163. userdata = args->data;
  164. statusloc = &args->info->status;
  165. /* Wake up the parent thread */
  166. Signal(args->wait,SIGBREAKF_CTRL_E);
  167. /* Run the function */
  168. *statusloc = userfunc(userdata);
  169. }
  170. SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data)
  171. {
  172. SDL_Thread *thread;
  173. thread_args *args;
  174. int ret;
  175. /* Allocate memory for the thread info structure */
  176. thread = (SDL_Thread *)malloc(sizeof(*thread));
  177. if ( thread == NULL ) {
  178. SDL_OutOfMemory();
  179. return(NULL);
  180. }
  181. memset(thread, 0, (sizeof *thread));
  182. thread->status = -1;
  183. /* Set up the arguments for the thread */
  184. args = (thread_args *)malloc(sizeof(*args));
  185. if ( args == NULL ) {
  186. SDL_OutOfMemory();
  187. free(thread);
  188. return(NULL);
  189. }
  190. args->func = fn;
  191. args->data = data;
  192. args->info = thread;
  193. args->wait = FindTask(NULL);
  194. if ( args->wait == NULL ) {
  195. free(thread);
  196. free(args);
  197. SDL_OutOfMemory();
  198. return(NULL);
  199. }
  200. /* Add the thread to the list of available threads */
  201. SDL_AddThread(thread);
  202. D(bug("Starting thread...n"));
  203. /* Create the thread and go! */
  204. ret = SDL_SYS_CreateThread(thread, args);
  205. if ( ret >= 0 ) {
  206. D(bug("Waiting for thread CTRL_E...n"));
  207. /* Wait for the thread function to use arguments */
  208. Wait(SIGBREAKF_CTRL_E);
  209. D(bug("  Arrived."));
  210. } else {
  211. /* Oops, failed.  Gotta free everything */
  212. SDL_DelThread(thread);
  213. free(thread);
  214. thread = NULL;
  215. }
  216. free(args);
  217. /* Everything is running now */
  218. return(thread);
  219. }
  220. void SDL_WaitThread(SDL_Thread *thread, int *status)
  221. {
  222. if ( thread ) {
  223. SDL_SYS_WaitThread(thread);
  224. if ( status ) {
  225. *status = thread->status;
  226. }
  227. SDL_DelThread(thread);
  228. free(thread);
  229. }
  230. }
  231. Uint32 SDL_GetThreadID(SDL_Thread *thread)
  232. {
  233. Uint32 id;
  234. if ( thread ) {
  235. id = thread->threadid;
  236. } else {
  237. id = SDL_ThreadID();
  238. }
  239. return(id);
  240. }
  241. void SDL_KillThread(SDL_Thread *thread)
  242. {
  243. if ( thread ) {
  244. SDL_SYS_KillThread(thread);
  245. SDL_WaitThread(thread, NULL);
  246. }
  247. }