Home | History | Annotate | Download | only in win32
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 /* Semaphore functions using the Win32 API */
     25 
     26 #define WIN32_LEAN_AND_MEAN
     27 #include <windows.h>
     28 
     29 #include "SDL_thread.h"
     30 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
     31 #include "win_ce_semaphore.h"
     32 #endif
     33 
     34 
     35 struct SDL_semaphore {
     36 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
     37 	SYNCHHANDLE id;
     38 #else
     39 	HANDLE id;
     40 #endif
     41 	Uint32 volatile count;
     42 };
     43 
     44 
     45 /* Create a semaphore */
     46 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
     47 {
     48 	SDL_sem *sem;
     49 
     50 	/* Allocate sem memory */
     51 	sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
     52 	if ( sem ) {
     53 		/* Create the semaphore, with max value 32K */
     54 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
     55 		sem->id = CreateSemaphoreCE(NULL, initial_value, 32*1024, NULL);
     56 #else
     57 		sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL);
     58 #endif
     59 		sem->count = initial_value;
     60 		if ( ! sem->id ) {
     61 			SDL_SetError("Couldn't create semaphore");
     62 			SDL_free(sem);
     63 			sem = NULL;
     64 		}
     65 	} else {
     66 		SDL_OutOfMemory();
     67 	}
     68 	return(sem);
     69 }
     70 
     71 /* Free the semaphore */
     72 void SDL_DestroySemaphore(SDL_sem *sem)
     73 {
     74 	if ( sem ) {
     75 		if ( sem->id ) {
     76 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
     77 			CloseSynchHandle(sem->id);
     78 #else
     79 			CloseHandle(sem->id);
     80 #endif
     81 			sem->id = 0;
     82 		}
     83 		SDL_free(sem);
     84 	}
     85 }
     86 
     87 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
     88 {
     89 	int retval;
     90 	DWORD dwMilliseconds;
     91 
     92 	if ( ! sem ) {
     93 		SDL_SetError("Passed a NULL sem");
     94 		return -1;
     95 	}
     96 
     97 	if ( timeout == SDL_MUTEX_MAXWAIT ) {
     98 		dwMilliseconds = INFINITE;
     99 	} else {
    100 		dwMilliseconds = (DWORD)timeout;
    101 	}
    102 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
    103 	switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
    104 #else
    105 	switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
    106 #endif
    107 	    case WAIT_OBJECT_0:
    108 		--sem->count;
    109 		retval = 0;
    110 		break;
    111 	    case WAIT_TIMEOUT:
    112 		retval = SDL_MUTEX_TIMEDOUT;
    113 		break;
    114 	    default:
    115 		SDL_SetError("WaitForSingleObject() failed");
    116 		retval = -1;
    117 		break;
    118 	}
    119 	return retval;
    120 }
    121 
    122 int SDL_SemTryWait(SDL_sem *sem)
    123 {
    124 	return SDL_SemWaitTimeout(sem, 0);
    125 }
    126 
    127 int SDL_SemWait(SDL_sem *sem)
    128 {
    129 	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
    130 }
    131 
    132 /* Returns the current count of the semaphore */
    133 Uint32 SDL_SemValue(SDL_sem *sem)
    134 {
    135 	if ( ! sem ) {
    136 		SDL_SetError("Passed a NULL sem");
    137 		return 0;
    138 	}
    139 	return sem->count;
    140 }
    141 
    142 int SDL_SemPost(SDL_sem *sem)
    143 {
    144 	if ( ! sem ) {
    145 		SDL_SetError("Passed a NULL sem");
    146 		return -1;
    147 	}
    148 	/* Increase the counter in the first place, because
    149 	 * after a successful release the semaphore may
    150 	 * immediately get destroyed by another thread which
    151 	 * is waiting for this semaphore.
    152 	 */
    153 	++sem->count;
    154 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
    155 	if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) {
    156 #else
    157 	if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) {
    158 #endif
    159 		--sem->count;	/* restore */
    160 		SDL_SetError("ReleaseSemaphore() failed");
    161 		return -1;
    162 	}
    163 	return 0;
    164 }
    165