about summary refs log tree commit diff
path: root/src/engine/external/glfw/lib/win32/win32_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/external/glfw/lib/win32/win32_thread.c')
-rw-r--r--src/engine/external/glfw/lib/win32/win32_thread.c511
1 files changed, 511 insertions, 0 deletions
diff --git a/src/engine/external/glfw/lib/win32/win32_thread.c b/src/engine/external/glfw/lib/win32/win32_thread.c
new file mode 100644
index 00000000..159347a7
--- /dev/null
+++ b/src/engine/external/glfw/lib/win32/win32_thread.c
@@ -0,0 +1,511 @@
+//========================================================================

+// GLFW - An OpenGL framework

+// File:        win32_thread.c

+// Platform:    Windows

+// API version: 2.6

+// WWW:         http://glfw.sourceforge.net

+//------------------------------------------------------------------------

+// Copyright (c) 2002-2006 Camilla Berglund

+//

+// This software is provided 'as-is', without any express or implied

+// warranty. In no event will the authors be held liable for any damages

+// arising from the use of this software.

+//

+// Permission is granted to anyone to use this software for any purpose,

+// including commercial applications, and to alter it and redistribute it

+// freely, subject to the following restrictions:

+//

+// 1. The origin of this software must not be misrepresented; you must not

+//    claim that you wrote the original software. If you use this software

+//    in a product, an acknowledgment in the product documentation would

+//    be appreciated but is not required.

+//

+// 2. Altered source versions must be plainly marked as such, and must not

+//    be misrepresented as being the original software.

+//

+// 3. This notice may not be removed or altered from any source

+//    distribution.

+//

+//========================================================================

+

+#include "internal.h"

+

+

+//************************************************************************

+// This is an implementation of POSIX "compatible" condition variables for

+// Win32, as described by Douglas C. Schmidt and Irfan Pyarali:

+// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html

+//************************************************************************

+

+enum {

+    _GLFW_COND_SIGNAL     = 0,

+    _GLFW_COND_BROADCAST  = 1

+};

+

+typedef struct {

+    // Signal and broadcast event HANDLEs

+    HANDLE events[ 2 ];

+

+    // Count of the number of waiters

+    unsigned int waiters_count;

+

+    // Serialize access to <waiters_count>

+    CRITICAL_SECTION waiters_count_lock;

+} _GLFWcond;

+

+

+

+//************************************************************************

+//****                  GLFW internal functions                       ****

+//************************************************************************

+

+//========================================================================

+// _glfwNewThread() - This is simply a "wrapper" for calling the user

+// thread function.

+//========================================================================

+

+DWORD WINAPI _glfwNewThread( LPVOID lpParam )

+{

+    GLFWthreadfun threadfun;

+    _GLFWthread   *t;

+

+    // Get pointer to thread information for current thread

+    t = _glfwGetThreadPointer( _glfwPlatformGetThreadID() );

+    if( t == NULL )

+    {

+        return 0;

+    }

+

+    // Get user thread function pointer

+    threadfun = t->Function;

+

+    // Call the user thread function

+    threadfun( (void *) lpParam );

+

+    // Remove thread from thread list

+    ENTER_THREAD_CRITICAL_SECTION

+    _glfwRemoveThread( t );

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // When the thread function returns, the thread will die...

+    return 0;

+}

+

+

+

+//************************************************************************

+//****                     GLFW user functions                        ****

+//************************************************************************

+

+//========================================================================

+// _glfwPlatformCreateThread() - Create a new thread

+//========================================================================

+

+GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )

+{

+    GLFWthread  ID;

+    _GLFWthread *t, *t_tmp;

+    HANDLE      hThread;

+    DWORD       dwThreadId;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Create a new thread information memory area

+    t = (_GLFWthread *) malloc( sizeof(_GLFWthread) );

+    if( t == NULL )

+    {

+        // Leave critical section

+        LEAVE_THREAD_CRITICAL_SECTION

+        return -1;

+    }

+

+    // Get a new unique thread id

+    ID = _glfwThrd.NextID ++;

+

+    // Store thread information in the thread list

+    t->Function = fun;

+    t->ID       = ID;

+

+    // Create thread

+    hThread = CreateThread(

+        NULL,              // Default security attributes

+        0,                 // Default stack size (1 MB)

+        _glfwNewThread,    // Thread function (a wrapper function)

+        (LPVOID)arg,       // Argument to thread is the user argument

+        0,                 // Default creation flags

+        &dwThreadId        // Returned thread identifier

+    );

+

+    // Did the thread creation fail?

+    if( hThread == NULL )

+    {

+        free( (void *) t );

+        LEAVE_THREAD_CRITICAL_SECTION

+        return -1;

+    }

+

+    // Store more thread information in the thread list

+    t->Handle = hThread;

+    t->WinID  = dwThreadId;

+

+    // Append thread to thread list

+    t_tmp = &_glfwThrd.First;

+    while( t_tmp->Next != NULL )

+    {

+        t_tmp = t_tmp->Next;

+    }

+    t_tmp->Next = t;

+    t->Previous = t_tmp;

+    t->Next     = NULL;

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Return the GLFW thread ID

+    return ID;

+}

+

+

+//========================================================================

+// _glfwPlatformDestroyThread() - Kill a thread. NOTE: THIS IS A VERY

+// DANGEROUS OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME

+// SITUATIONS!

+//========================================================================

+

+void _glfwPlatformDestroyThread( GLFWthread ID )

+{

+    _GLFWthread *t;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Get thread information pointer

+    t = _glfwGetThreadPointer( ID );

+    if( t == NULL )

+    {

+        LEAVE_THREAD_CRITICAL_SECTION

+        return;

+    }

+

+    // Simply murder the process, no mercy!

+    if( TerminateThread( t->Handle, 0 ) )

+    {

+        // Close thread handle

+        CloseHandle( t->Handle );

+

+        // Remove thread from thread list

+        _glfwRemoveThread( t );

+    }

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+}

+

+

+//========================================================================

+// _glfwPlatformWaitThread() - Wait for a thread to die

+//========================================================================

+

+int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )

+{

+    DWORD       result;

+    HANDLE      hThread;

+    _GLFWthread *t;

+

+    // Enter critical section

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Get thread information pointer

+    t = _glfwGetThreadPointer( ID );

+

+    // Is the thread already dead?

+    if( t == NULL )

+    {

+        LEAVE_THREAD_CRITICAL_SECTION

+        return GL_TRUE;

+    }

+

+    // Get thread handle

+    hThread = t->Handle;

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Wait for thread to die

+    if( waitmode == GLFW_WAIT )

+    {

+        result = WaitForSingleObject( hThread, INFINITE );

+    }

+    else if( waitmode == GLFW_NOWAIT )

+    {

+        result = WaitForSingleObject( hThread, 0 );

+    }

+    else

+    {

+        return GL_FALSE;

+    }

+

+    // Did we have a time-out?

+    if( result == WAIT_TIMEOUT )

+    {

+        return GL_FALSE;

+    }

+    return GL_TRUE;

+}

+

+

+//========================================================================

+// _glfwPlatformGetThreadID() - Return the thread ID for the current

+// thread

+//========================================================================

+

+GLFWthread _glfwPlatformGetThreadID( void )

+{

+    _GLFWthread *t;

+    GLFWthread  ID = -1;

+    DWORD       WinID;

+

+    // Get Windows thread ID

+    WinID = GetCurrentThreadId();

+

+    // Enter critical section (to avoid an inconsistent thread list)

+    ENTER_THREAD_CRITICAL_SECTION

+

+    // Loop through entire list of threads to find the matching Windows

+    // thread ID

+    for( t = &_glfwThrd.First; t != NULL; t = t->Next )

+    {

+        if( t->WinID == WinID )

+        {

+            ID = t->ID;

+            break;

+        }

+    }

+

+    // Leave critical section

+    LEAVE_THREAD_CRITICAL_SECTION

+

+    // Return the found GLFW thread identifier

+    return ID;

+}

+

+

+//========================================================================

+// _glfwPlatformCreateMutex() - Create a mutual exclusion object

+//========================================================================

+

+GLFWmutex _glfwPlatformCreateMutex( void )

+{

+    CRITICAL_SECTION *mutex;

+

+    // Allocate memory for mutex

+    mutex = (CRITICAL_SECTION *) malloc( sizeof(CRITICAL_SECTION) );

+    if( !mutex )

+    {

+        return NULL;

+    }

+

+    // Initialize mutex

+    InitializeCriticalSection( mutex );

+

+    // Cast to GLFWmutex and return

+    return (GLFWmutex) mutex;

+}

+

+

+//========================================================================

+// glfwDestroyMutex() - Destroy a mutual exclusion object

+//========================================================================

+

+void _glfwPlatformDestroyMutex( GLFWmutex mutex )

+{

+    // Destroy mutex

+    DeleteCriticalSection( (CRITICAL_SECTION *) mutex );

+    free( mutex );

+}

+

+

+//========================================================================

+// _glfwPlatformLockMutex() - Request access to a mutex

+//========================================================================

+

+void _glfwPlatformLockMutex( GLFWmutex mutex )

+{

+    // Wait for mutex to be released

+    EnterCriticalSection( (CRITICAL_SECTION *) mutex );

+}

+

+

+//========================================================================

+// _glfwPlatformUnlockMutex() - Release a mutex

+//========================================================================

+

+void _glfwPlatformUnlockMutex( GLFWmutex mutex )

+{

+    // Release mutex

+    LeaveCriticalSection( (CRITICAL_SECTION *) mutex );

+}

+

+

+//========================================================================

+// _glfwPlatformCreateCond() - Create a new condition variable object

+//========================================================================

+

+GLFWcond _glfwPlatformCreateCond( void )

+{

+    _GLFWcond   *cond;

+

+    // Allocate memory for condition variable

+    cond = (_GLFWcond *) malloc( sizeof(_GLFWcond) );

+    if( !cond )

+    {

+        return NULL;

+    }

+

+    // Initialize condition variable

+    cond->waiters_count = 0;

+    cond->events[ _GLFW_COND_SIGNAL ]    = CreateEvent( NULL, FALSE,

+                                                        FALSE, NULL );

+    cond->events[ _GLFW_COND_BROADCAST ] = CreateEvent( NULL, TRUE,

+                                                        FALSE, NULL );

+    InitializeCriticalSection( &cond->waiters_count_lock );

+

+    // Cast to GLFWcond and return

+    return (GLFWcond) cond;

+}

+

+

+//========================================================================

+// _glfwPlatformDestroyCond() - Destroy a condition variable object

+//========================================================================

+

+void _glfwPlatformDestroyCond( GLFWcond cond )

+{

+    // Close the condition variable handles

+    CloseHandle( ((_GLFWcond *)cond)->events[ _GLFW_COND_SIGNAL ] );

+    CloseHandle( ((_GLFWcond *)cond)->events[ _GLFW_COND_BROADCAST ] );

+

+    // Delete critical section

+    DeleteCriticalSection( &((_GLFWcond *)cond)->waiters_count_lock );

+

+    // Free memory for condition variable

+    free( (void *) cond );

+}

+

+

+//========================================================================

+// _glfwPlatformWaitCond() - Wait for a condition to be raised

+//========================================================================

+

+void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex,

+    double timeout )

+{

+    _GLFWcond *cv = (_GLFWcond *) cond;

+    int       result, last_waiter;

+    DWORD     timeout_ms;

+

+    // Avoid race conditions

+    EnterCriticalSection( &cv->waiters_count_lock );

+    cv->waiters_count ++;

+    LeaveCriticalSection( &cv->waiters_count_lock );

+

+    // It's ok to release the mutex here since Win32 manual-reset events

+    // maintain state when used with SetEvent()

+    LeaveCriticalSection( (CRITICAL_SECTION *) mutex );

+

+    // Translate timeout into milliseconds

+    if( timeout >= GLFW_INFINITY )

+    {

+        timeout_ms = INFINITE;

+    }

+    else

+    {

+        timeout_ms = (DWORD) (1000.0 * timeout + 0.5);

+        if( timeout_ms <= 0 )

+        {

+            timeout_ms = 1;

+        }

+    }

+

+    // Wait for either event to become signaled due to glfwSignalCond or

+    // glfwBroadcastCond being called

+    result = WaitForMultipleObjects( 2, cv->events, FALSE, timeout_ms );

+

+    // Check if we are the last waiter

+    EnterCriticalSection( &cv->waiters_count_lock );

+    cv->waiters_count --;

+    last_waiter = (result == WAIT_OBJECT_0 + _GLFW_COND_BROADCAST) &&

+                  (cv->waiters_count == 0);

+    LeaveCriticalSection( &cv->waiters_count_lock );

+

+    // Some thread called glfwBroadcastCond

+    if( last_waiter )

+    {

+        // We're the last waiter to be notified or to stop waiting, so

+        // reset the manual event

+        ResetEvent( cv->events[ _GLFW_COND_BROADCAST ] );

+    }

+

+    // Reacquire the mutex

+    EnterCriticalSection( (CRITICAL_SECTION *) mutex );

+}

+

+

+//========================================================================

+// _glfwPlatformSignalCond() - Signal a condition to one waiting thread

+//========================================================================

+

+void _glfwPlatformSignalCond( GLFWcond cond )

+{

+    _GLFWcond *cv = (_GLFWcond *) cond;

+    int       have_waiters;

+

+    // Avoid race conditions

+    EnterCriticalSection( &cv->waiters_count_lock );

+    have_waiters = cv->waiters_count > 0;

+    LeaveCriticalSection( &cv->waiters_count_lock );

+

+    if( have_waiters )

+    {

+        SetEvent( cv->events[ _GLFW_COND_SIGNAL ] );

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformBroadcastCond() - Broadcast a condition to all waiting

+// threads

+//========================================================================

+

+void _glfwPlatformBroadcastCond( GLFWcond cond )

+{

+    _GLFWcond *cv = (_GLFWcond *) cond;

+    int       have_waiters;

+

+    // Avoid race conditions

+    EnterCriticalSection( &cv->waiters_count_lock );

+    have_waiters = cv->waiters_count > 0;

+    LeaveCriticalSection( &cv->waiters_count_lock );

+

+    if( have_waiters )

+    {

+        SetEvent( cv->events[ _GLFW_COND_BROADCAST ] );

+    }

+}

+

+

+//========================================================================

+// _glfwPlatformGetNumberOfProcessors() - Return the number of processors

+// in the system.

+//========================================================================

+

+int _glfwPlatformGetNumberOfProcessors( void )

+{

+    SYSTEM_INFO si;

+

+    // Get hardware system information

+    GetSystemInfo( &si );

+

+    return (int) si.dwNumberOfProcessors;

+}