Could people who know threads and semaphores take a look at this
implementation and let us know if it has flaws? It’s also in SDL CVS,
but not guaranteed to stay.
See ya!–
-Sam Lantinga, Lead Programmer, Loki Entertainment Software
-------------- next part --------------
/*
SDL - Simple DirectMedia Layer
Copyright © 1997, 1998, 1999, 2000 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
slouken at devolution.com
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_mutex.c,v 1.2.2.5 2000/03/31 05:22:50 hercules Exp $";
#endif
/* An implementation of counting semaphores using mutexes */
#include “SDL_error.h”
#include “SDL_mutex.h”
#include “SDL_semaphore.h”
struct SDL_semaphore
{
int count;
SDL_mutex *count_lock;
SDL_mutex *wait_lock;
};
SDL_sem *SDL_CreateSemaphore(int initial_value)
{
SDL_sem *sem;
if ( initial_value < 0 ) {
SDL_SetError("Cannot create semaphore with negative value");
return(0);
}
sem = (SDL_sem *)malloc(sizeof(*sem));
if ( ! sem ) {
SDL_OutOfMemory();
return(0);
}
sem->count = initial_value;
sem->count_lock = SDL_CreateMutex();
sem->wait_lock = SDL_CreateMutex();
if ( ! sem->count_lock || ! sem->wait_lock ) {
SDL_DestroySemaphore(sem);
return(0);
}
SDL_LockMutex(sem->wait_lock);
return(sem);
}
void SDL_DestroySemaphore(SDL_sem sem)
{
if ( sem ) {
if ( sem->count_lock ) {
/ Small attempt at releasing threads */
SDL_LockMutex(sem->count_lock);
while ( sem->count < 0 ) {
SDL_UnlockMutex(sem->wait_lock);
++sem->count;
}
SDL_UnlockMutex(sem->count_lock);
SDL_DestroyMutex(sem->count_lock);
}
if ( sem->wait_lock ) {
SDL_DestroyMutex(sem->wait_lock);
}
free(sem);
}
}
void SDL_SemWait(SDL_sem *sem)
{
SDL_bool must_wait;
SDL_LockMutex(sem->count_lock);
if ( sem->count > 0 ) {
must_wait = SDL_FALSE;
} else {
must_wait = SDL_TRUE;
}
--sem->count;
SDL_UnlockMutex(sem->count_lock);
if ( must_wait ) {
SDL_LockMutex(sem->wait_lock);
}
}
SDL_bool SDL_SemTryWait(SDL_sem *sem)
{
SDL_bool must_wait;
SDL_LockMutex(sem->count_lock);
if ( sem->count > 0 ) {
must_wait = SDL_FALSE;
} else {
must_wait = SDL_TRUE;
}
if ( ! must_wait ) {
--sem->count;
}
SDL_UnlockMutex(sem->count_lock);
return !must_wait;
}
int SDL_SemValue(SDL_sem *sem)
{
int value;
if ( sem->count < 0 ) {
value = 0;
} else {
value = sem->count;
}
return value;
}
void SDL_SemPost(SDL_sem *sem)
{
SDL_LockMutex(sem->count_lock);
if ( sem->count < 0 ) {
SDL_UnlockMutex(sem->wait_lock);
}
++sem->count;
SDL_UnlockMutex(sem->count_lock);
}