From 20f7478da933e74238e868bb592efb4e783ebdb9 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 2 Jun 2014 11:55:18 +0200 Subject: it's now thread safe --- test/Makefile | 2 +- wglarb.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index 059b790..946272e 100644 --- a/test/Makefile +++ b/test/Makefile @@ -16,7 +16,7 @@ layered64.exe: layered.c layered64_rc.o $(CC64) $(CFLAGS) -o layered64.exe layered.c layered64_rc.o ../wglarb.c $(LIBS) -Wl,--subsystem,windows layered32.exe: layered.c layered32_rc.o - $(CC32) $(CFLAGS) -o layered32.exe layered.c layered32_rc.o ../wglarb.c $(LIBS) -Wl,--subsystem,windows + $(CC32) -march=i686 $(CFLAGS) -o layered32.exe layered.c layered32_rc.o ../wglarb.c $(LIBS) -Wl,--subsystem,windows layered64_rc.o: layered.rc manifest.xml diff --git a/wglarb.c b/wglarb.c index 306cc73..7ccc320 100644 --- a/wglarb.c +++ b/wglarb.c @@ -22,6 +22,51 @@ THE SOFTWARE. #include #include "wglarb.h" +#define wglarb_BuildAssert(cond) ((void)sizeof(char[1 - 2*!(cond)])) + +static HANDLE wglarb_intermediary_mutex = NULL; + +static DWORD wglarb_intermediary_lock(void) +{ + wglarb_BuildAssert( sizeof(PVOID) == sizeof(HANDLE) ); + + if( !wglarb_intermediary_mutex ) { + /* Between testing for the validity of the mutex handle, + * creating a new mutex handle and using the interlocked + * exchange there is a race. */ + + HANDLE const new_mutex = + CreateMutex(NULL, TRUE, NULL); + + HANDLE const dst_mutex = + InterlockedCompareExchangePointer( + &wglarb_intermediary_mutex, + new_mutex, + NULL ); + + if( dst_mutex ) { + /* In this case we lost the race and another thread + * beat this thread in creating a mutex object. + * Clean up and wait for the proper mutex. */ + ReleaseMutex(new_mutex); + CloseHandle(new_mutex); + goto wait_for_mutex; + } + + /* mutex created in one time initialization and hold + * by calling thread. Return signaled status. */ + return WAIT_OBJECT_0; + } + +wait_for_mutex: + return WaitForSingleObject(wglarb_intermediary_mutex, INFINITE); +} + +static BOOL wglarb_intermediary_unlock(void) +{ + return ReleaseMutex(wglarb_intermediary_mutex); +} + #define WGLARB_INTERMEDIARY_CLASS "wglarb intermediary" #define WGLARB_INTERMEDIARY_STYLE (WS_CLIPSIBLINGS|WS_CLIPCHILDREN) #define WGLARB_INTERMEDIARY_EXSTYLE 0 @@ -127,9 +172,14 @@ HGLRC WINAPI wglarb_CreateContextAttribsARB( HGLRC hShareContext, const int *attribList) { + if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) { + return NULL; + } + HDC hOrigDC; HGLRC hOrigRC; if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) { + wglarb_intermediary_unlock(); return NULL; } @@ -143,6 +193,7 @@ HGLRC WINAPI wglarb_CreateContextAttribsARB( } wglMakeCurrent(hOrigDC, hOrigRC); + wglarb_intermediary_unlock(); return ret; } @@ -154,9 +205,14 @@ BOOL WINAPI wglarb_ChoosePixelFormatARB( int *piFormats, UINT *nNumFormats) { + if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) { + return FALSE; + } + HDC hOrigDC; HGLRC hOrigRC; if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) { + wglarb_intermediary_unlock(); return FALSE; } @@ -176,5 +232,6 @@ BOOL WINAPI wglarb_ChoosePixelFormatARB( } wglMakeCurrent(hOrigDC, hOrigRC); + wglarb_intermediary_unlock(); return ret; } -- cgit v1.2.3