PageRenderTime 1516ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Angel-3.1/Code/Angel/Libraries/glfw-2.7.7/lib/win32/win32_thread.c

https://github.com/chrishaukap/GameDev
C | 506 lines | 246 code | 110 blank | 150 comment | 32 complexity | ffbd71fcd00cb92d4ea11705db3b9d14 MD5 | raw file
  1. //========================================================================
  2. // GLFW - An OpenGL framework
  3. // Platform: Win32/WGL
  4. // API version: 2.7
  5. // WWW: http://www.glfw.org/
  6. //------------------------------------------------------------------------
  7. // Copyright (c) 2002-2006 Marcus Geelnard
  8. // Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
  9. //
  10. // This software is provided 'as-is', without any express or implied
  11. // warranty. In no event will the authors be held liable for any damages
  12. // arising from the use of this software.
  13. //
  14. // Permission is granted to anyone to use this software for any purpose,
  15. // including commercial applications, and to alter it and redistribute it
  16. // freely, subject to the following restrictions:
  17. //
  18. // 1. The origin of this software must not be misrepresented; you must not
  19. // claim that you wrote the original software. If you use this software
  20. // in a product, an acknowledgment in the product documentation would
  21. // be appreciated but is not required.
  22. //
  23. // 2. Altered source versions must be plainly marked as such, and must not
  24. // be misrepresented as being the original software.
  25. //
  26. // 3. This notice may not be removed or altered from any source
  27. // distribution.
  28. //
  29. //========================================================================
  30. #include "internal.h"
  31. //************************************************************************
  32. // This is an implementation of POSIX "compatible" condition variables for
  33. // Win32, as described by Douglas C. Schmidt and Irfan Pyarali:
  34. // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
  35. //************************************************************************
  36. enum {
  37. _GLFW_COND_SIGNAL = 0,
  38. _GLFW_COND_BROADCAST = 1
  39. };
  40. typedef struct {
  41. // Signal and broadcast event HANDLEs
  42. HANDLE events[ 2 ];
  43. // Count of the number of waiters
  44. unsigned int waiters_count;
  45. // Serialize access to <waiters_count>
  46. CRITICAL_SECTION waiters_count_lock;
  47. } _GLFWcond;
  48. //************************************************************************
  49. //**** GLFW internal functions ****
  50. //************************************************************************
  51. //========================================================================
  52. // This is simply a "wrapper" for calling the user thread function.
  53. //========================================================================
  54. DWORD WINAPI _glfwNewThread( LPVOID lpParam )
  55. {
  56. GLFWthreadfun threadfun;
  57. _GLFWthread *t;
  58. // Get pointer to thread information for current thread
  59. t = _glfwGetThreadPointer( _glfwPlatformGetThreadID() );
  60. if( t == NULL )
  61. {
  62. return 0;
  63. }
  64. // Get user thread function pointer
  65. threadfun = t->Function;
  66. // Call the user thread function
  67. threadfun( (void *) lpParam );
  68. // Remove thread from thread list
  69. ENTER_THREAD_CRITICAL_SECTION
  70. _glfwRemoveThread( t );
  71. LEAVE_THREAD_CRITICAL_SECTION
  72. // When the thread function returns, the thread will die...
  73. return 0;
  74. }
  75. //************************************************************************
  76. //**** GLFW user functions ****
  77. //************************************************************************
  78. //========================================================================
  79. // Create a new thread
  80. //========================================================================
  81. GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )
  82. {
  83. GLFWthread ID;
  84. _GLFWthread *t, *t_tmp;
  85. HANDLE hThread;
  86. DWORD dwThreadId;
  87. // Enter critical section
  88. ENTER_THREAD_CRITICAL_SECTION
  89. // Create a new thread information memory area
  90. t = (_GLFWthread *) malloc( sizeof(_GLFWthread) );
  91. if( t == NULL )
  92. {
  93. // Leave critical section
  94. LEAVE_THREAD_CRITICAL_SECTION
  95. return -1;
  96. }
  97. // Get a new unique thread id
  98. ID = _glfwThrd.NextID ++;
  99. // Store thread information in the thread list
  100. t->Function = fun;
  101. t->ID = ID;
  102. // Create thread
  103. hThread = CreateThread(
  104. NULL, // Default security attributes
  105. 0, // Default stack size (1 MB)
  106. _glfwNewThread, // Thread function (a wrapper function)
  107. (LPVOID)arg, // Argument to thread is the user argument
  108. 0, // Default creation flags
  109. &dwThreadId // Returned thread identifier
  110. );
  111. // Did the thread creation fail?
  112. if( hThread == NULL )
  113. {
  114. free( (void *) t );
  115. LEAVE_THREAD_CRITICAL_SECTION
  116. return -1;
  117. }
  118. // Store more thread information in the thread list
  119. t->Handle = hThread;
  120. t->WinID = dwThreadId;
  121. // Append thread to thread list
  122. t_tmp = &_glfwThrd.First;
  123. while( t_tmp->Next != NULL )
  124. {
  125. t_tmp = t_tmp->Next;
  126. }
  127. t_tmp->Next = t;
  128. t->Previous = t_tmp;
  129. t->Next = NULL;
  130. // Leave critical section
  131. LEAVE_THREAD_CRITICAL_SECTION
  132. // Return the GLFW thread ID
  133. return ID;
  134. }
  135. //========================================================================
  136. // Kill a thread. NOTE: THIS IS A VERY DANGEROUS OPERATION, AND SHOULD NOT
  137. // BE USED EXCEPT IN EXTREME SITUATIONS!
  138. //========================================================================
  139. void _glfwPlatformDestroyThread( GLFWthread ID )
  140. {
  141. _GLFWthread *t;
  142. // Enter critical section
  143. ENTER_THREAD_CRITICAL_SECTION
  144. // Get thread information pointer
  145. t = _glfwGetThreadPointer( ID );
  146. if( t == NULL )
  147. {
  148. LEAVE_THREAD_CRITICAL_SECTION
  149. return;
  150. }
  151. // Simply murder the process, no mercy!
  152. if( TerminateThread( t->Handle, 0 ) )
  153. {
  154. // Close thread handle
  155. CloseHandle( t->Handle );
  156. // Remove thread from thread list
  157. _glfwRemoveThread( t );
  158. }
  159. // Leave critical section
  160. LEAVE_THREAD_CRITICAL_SECTION
  161. }
  162. //========================================================================
  163. // Wait for a thread to die
  164. //========================================================================
  165. int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )
  166. {
  167. DWORD result;
  168. HANDLE hThread;
  169. _GLFWthread *t;
  170. // Enter critical section
  171. ENTER_THREAD_CRITICAL_SECTION
  172. // Get thread information pointer
  173. t = _glfwGetThreadPointer( ID );
  174. // Is the thread already dead?
  175. if( t == NULL )
  176. {
  177. LEAVE_THREAD_CRITICAL_SECTION
  178. return GL_TRUE;
  179. }
  180. // Get thread handle
  181. hThread = t->Handle;
  182. // Leave critical section
  183. LEAVE_THREAD_CRITICAL_SECTION
  184. // Wait for thread to die
  185. if( waitmode == GLFW_WAIT )
  186. {
  187. result = WaitForSingleObject( hThread, INFINITE );
  188. }
  189. else if( waitmode == GLFW_NOWAIT )
  190. {
  191. result = WaitForSingleObject( hThread, 0 );
  192. }
  193. else
  194. {
  195. return GL_FALSE;
  196. }
  197. // Did we have a time-out?
  198. if( result == WAIT_TIMEOUT )
  199. {
  200. return GL_FALSE;
  201. }
  202. return GL_TRUE;
  203. }
  204. //========================================================================
  205. // Return the thread ID for the current thread
  206. //========================================================================
  207. GLFWthread _glfwPlatformGetThreadID( void )
  208. {
  209. _GLFWthread *t;
  210. GLFWthread ID = -1;
  211. DWORD WinID;
  212. // Get Windows thread ID
  213. WinID = GetCurrentThreadId();
  214. // Enter critical section (to avoid an inconsistent thread list)
  215. ENTER_THREAD_CRITICAL_SECTION
  216. // Loop through entire list of threads to find the matching Windows
  217. // thread ID
  218. for( t = &_glfwThrd.First; t != NULL; t = t->Next )
  219. {
  220. if( t->WinID == WinID )
  221. {
  222. ID = t->ID;
  223. break;
  224. }
  225. }
  226. // Leave critical section
  227. LEAVE_THREAD_CRITICAL_SECTION
  228. // Return the found GLFW thread identifier
  229. return ID;
  230. }
  231. //========================================================================
  232. // Create a mutual exclusion object
  233. //========================================================================
  234. GLFWmutex _glfwPlatformCreateMutex( void )
  235. {
  236. CRITICAL_SECTION *mutex;
  237. // Allocate memory for mutex
  238. mutex = (CRITICAL_SECTION *) malloc( sizeof(CRITICAL_SECTION) );
  239. if( !mutex )
  240. {
  241. return NULL;
  242. }
  243. // Initialize mutex
  244. InitializeCriticalSection( mutex );
  245. // Cast to GLFWmutex and return
  246. return (GLFWmutex) mutex;
  247. }
  248. //========================================================================
  249. // Destroy a mutual exclusion object
  250. //========================================================================
  251. void _glfwPlatformDestroyMutex( GLFWmutex mutex )
  252. {
  253. // Destroy mutex
  254. DeleteCriticalSection( (CRITICAL_SECTION *) mutex );
  255. free( mutex );
  256. }
  257. //========================================================================
  258. // Request access to a mutex
  259. //========================================================================
  260. void _glfwPlatformLockMutex( GLFWmutex mutex )
  261. {
  262. // Wait for mutex to be released
  263. EnterCriticalSection( (CRITICAL_SECTION *) mutex );
  264. }
  265. //========================================================================
  266. // Release a mutex
  267. //========================================================================
  268. void _glfwPlatformUnlockMutex( GLFWmutex mutex )
  269. {
  270. // Release mutex
  271. LeaveCriticalSection( (CRITICAL_SECTION *) mutex );
  272. }
  273. //========================================================================
  274. // Create a new condition variable object
  275. //========================================================================
  276. GLFWcond _glfwPlatformCreateCond( void )
  277. {
  278. _GLFWcond *cond;
  279. // Allocate memory for condition variable
  280. cond = (_GLFWcond *) malloc( sizeof(_GLFWcond) );
  281. if( !cond )
  282. {
  283. return NULL;
  284. }
  285. // Initialize condition variable
  286. cond->waiters_count = 0;
  287. cond->events[ _GLFW_COND_SIGNAL ] = CreateEvent( NULL, FALSE,
  288. FALSE, NULL );
  289. cond->events[ _GLFW_COND_BROADCAST ] = CreateEvent( NULL, TRUE,
  290. FALSE, NULL );
  291. InitializeCriticalSection( &cond->waiters_count_lock );
  292. // Cast to GLFWcond and return
  293. return (GLFWcond) cond;
  294. }
  295. //========================================================================
  296. // Destroy a condition variable object
  297. //========================================================================
  298. void _glfwPlatformDestroyCond( GLFWcond cond )
  299. {
  300. // Close the condition variable handles
  301. CloseHandle( ((_GLFWcond *)cond)->events[ _GLFW_COND_SIGNAL ] );
  302. CloseHandle( ((_GLFWcond *)cond)->events[ _GLFW_COND_BROADCAST ] );
  303. // Delete critical section
  304. DeleteCriticalSection( &((_GLFWcond *)cond)->waiters_count_lock );
  305. // Free memory for condition variable
  306. free( (void *) cond );
  307. }
  308. //========================================================================
  309. // Wait for a condition to be raised
  310. //========================================================================
  311. void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex, double timeout )
  312. {
  313. _GLFWcond *cv = (_GLFWcond *) cond;
  314. int result, last_waiter;
  315. DWORD timeout_ms;
  316. // Avoid race conditions
  317. EnterCriticalSection( &cv->waiters_count_lock );
  318. cv->waiters_count ++;
  319. LeaveCriticalSection( &cv->waiters_count_lock );
  320. // It's ok to release the mutex here since Win32 manual-reset events
  321. // maintain state when used with SetEvent()
  322. LeaveCriticalSection( (CRITICAL_SECTION *) mutex );
  323. // Translate timeout into milliseconds
  324. if( timeout >= GLFW_INFINITY )
  325. {
  326. timeout_ms = INFINITE;
  327. }
  328. else
  329. {
  330. timeout_ms = (DWORD) (1000.0 * timeout + 0.5);
  331. if( timeout_ms <= 0 )
  332. {
  333. timeout_ms = 1;
  334. }
  335. }
  336. // Wait for either event to become signaled due to glfwSignalCond or
  337. // glfwBroadcastCond being called
  338. result = WaitForMultipleObjects( 2, cv->events, FALSE, timeout_ms );
  339. // Check if we are the last waiter
  340. EnterCriticalSection( &cv->waiters_count_lock );
  341. cv->waiters_count --;
  342. last_waiter = (result == WAIT_OBJECT_0 + _GLFW_COND_BROADCAST) &&
  343. (cv->waiters_count == 0);
  344. LeaveCriticalSection( &cv->waiters_count_lock );
  345. // Some thread called glfwBroadcastCond
  346. if( last_waiter )
  347. {
  348. // We're the last waiter to be notified or to stop waiting, so
  349. // reset the manual event
  350. ResetEvent( cv->events[ _GLFW_COND_BROADCAST ] );
  351. }
  352. // Reacquire the mutex
  353. EnterCriticalSection( (CRITICAL_SECTION *) mutex );
  354. }
  355. //========================================================================
  356. // Signal a condition to one waiting thread
  357. //========================================================================
  358. void _glfwPlatformSignalCond( GLFWcond cond )
  359. {
  360. _GLFWcond *cv = (_GLFWcond *) cond;
  361. int have_waiters;
  362. // Avoid race conditions
  363. EnterCriticalSection( &cv->waiters_count_lock );
  364. have_waiters = cv->waiters_count > 0;
  365. LeaveCriticalSection( &cv->waiters_count_lock );
  366. if( have_waiters )
  367. {
  368. SetEvent( cv->events[ _GLFW_COND_SIGNAL ] );
  369. }
  370. }
  371. //========================================================================
  372. // Broadcast a condition to all waiting threads
  373. //========================================================================
  374. void _glfwPlatformBroadcastCond( GLFWcond cond )
  375. {
  376. _GLFWcond *cv = (_GLFWcond *) cond;
  377. int have_waiters;
  378. // Avoid race conditions
  379. EnterCriticalSection( &cv->waiters_count_lock );
  380. have_waiters = cv->waiters_count > 0;
  381. LeaveCriticalSection( &cv->waiters_count_lock );
  382. if( have_waiters )
  383. {
  384. SetEvent( cv->events[ _GLFW_COND_BROADCAST ] );
  385. }
  386. }
  387. //========================================================================
  388. // Return the number of processors in the system.
  389. //========================================================================
  390. int _glfwPlatformGetNumberOfProcessors( void )
  391. {
  392. SYSTEM_INFO si;
  393. // Get hardware system information
  394. GetSystemInfo( &si );
  395. return (int) si.dwNumberOfProcessors;
  396. }