146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* 246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL - Simple DirectMedia Layer 346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Copyright (C) 1997-2006 Sam Lantinga 446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is free software; you can redistribute it and/or 646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner modify it under the terms of the GNU Lesser General Public 746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License as published by the Free Software Foundation; either 846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner version 2.1 of the License, or (at your option) any later version. 946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner This library is distributed in the hope that it will be useful, 1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner but WITHOUT ANY WARRANTY; without even the implied warranty of 1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Lesser General Public License for more details. 1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner You should have received a copy of the GNU Lesser General Public 1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner License along with this library; if not, write to the Free Software 1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Sam Lantinga 2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner slouken@libsdl.org 2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/ 2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h" 2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Semaphore functions using the Win32 API */ 2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define WIN32_LEAN_AND_MEAN 2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <windows.h> 2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_thread.h" 3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "win_ce_semaphore.h" 3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstruct SDL_semaphore { 3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SYNCHHANDLE id; 3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner HANDLE id; 4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner Uint32 volatile count; 4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}; 4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Create a semaphore */ 4646be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerSDL_sem *SDL_CreateSemaphore(Uint32 initial_value) 4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_sem *sem; 4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Allocate sem memory */ 5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); 5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( sem ) { 5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Create the semaphore, with max value 32K */ 5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sem->id = CreateSemaphoreCE(NULL, initial_value, 32*1024, NULL); 5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL); 5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sem->count = initial_value; 6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! sem->id ) { 6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Couldn't create semaphore"); 6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(sem); 6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sem = NULL; 6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_OutOfMemory(); 6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return(sem); 6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Free the semaphore */ 7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_DestroySemaphore(SDL_sem *sem) 7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( sem ) { 7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( sem->id ) { 7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner CloseSynchHandle(sem->id); 7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner CloseHandle(sem->id); 8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner sem->id = 0; 8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_free(sem); 8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner int retval; 9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner DWORD dwMilliseconds; 9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! sem ) { 9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Passed a NULL sem"); 9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( timeout == SDL_MUTEX_MAXWAIT ) { 9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dwMilliseconds = INFINITE; 9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } else { 10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner dwMilliseconds = (DWORD)timeout; 10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) { 10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner switch (WaitForSingleObject(sem->id, dwMilliseconds)) { 10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case WAIT_OBJECT_0: 10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner --sem->count; 10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner retval = 0; 11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner case WAIT_TIMEOUT: 11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner retval = SDL_MUTEX_TIMEDOUT; 11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner default: 11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("WaitForSingleObject() failed"); 11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner retval = -1; 11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner break; 11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return retval; 12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemTryWait(SDL_sem *sem) 12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return SDL_SemWaitTimeout(sem, 0); 12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemWait(SDL_sem *sem) 12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); 13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Returns the current count of the semaphore */ 13346be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 SDL_SemValue(SDL_sem *sem) 13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! sem ) { 13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Passed a NULL sem"); 13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return 0; 13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return sem->count; 14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner 14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SemPost(SDL_sem *sem) 14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{ 14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ! sem ) { 14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("Passed a NULL sem"); 14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner /* Increase the counter in the first place, because 14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * after a successful release the semaphore may 15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * immediately get destroyed by another thread which 15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * is waiting for this semaphore. 15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner */ 15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner ++sem->count; 15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#if defined(_WIN32_WCE) && (_WIN32_WCE < 300) 15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) { 15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else 15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) { 15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif 15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner --sem->count; /* restore */ 16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner SDL_SetError("ReleaseSemaphore() failed"); 16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return -1; 16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner } 16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner return 0; 16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner} 165