src/thread/generic/SDL_syssem.c
author Sam Lantinga
Mon, 06 Feb 2006 08:28:51 +0000
changeset 1330 450721ad5436
parent 1312 c9b51268668f
child 1336 3692456e7b0f
permissions -rw-r--r--
It's now possible to build SDL without any C runtime at all on Windows,
using Visual C++ 2005
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@0
    22
slouken@0
    23
/* An implementation of semaphores using mutexes and condition variables */
slouken@0
    24
slouken@0
    25
#include "SDL_error.h"
slouken@0
    26
#include "SDL_timer.h"
slouken@0
    27
#include "SDL_thread.h"
slouken@1330
    28
#include "SDL_stdlib.h"
slouken@0
    29
#include "SDL_systhread_c.h"
slouken@0
    30
slouken@0
    31
slouken@0
    32
#ifdef DISABLE_THREADS
slouken@0
    33
slouken@0
    34
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
slouken@0
    35
{
slouken@0
    36
	SDL_SetError("SDL not configured with thread support");
slouken@0
    37
	return (SDL_sem *)0;
slouken@0
    38
}
slouken@0
    39
slouken@0
    40
void SDL_DestroySemaphore(SDL_sem *sem)
slouken@0
    41
{
slouken@0
    42
	return;
slouken@0
    43
}
slouken@0
    44
slouken@0
    45
int SDL_SemTryWait(SDL_sem *sem)
slouken@0
    46
{
slouken@0
    47
	SDL_SetError("SDL not configured with thread support");
slouken@0
    48
	return -1;
slouken@0
    49
}
slouken@0
    50
slouken@0
    51
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
slouken@0
    52
{
slouken@0
    53
	SDL_SetError("SDL not configured with thread support");
slouken@0
    54
	return -1;
slouken@0
    55
}
slouken@0
    56
slouken@0
    57
int SDL_SemWait(SDL_sem *sem)
slouken@0
    58
{
slouken@0
    59
	SDL_SetError("SDL not configured with thread support");
slouken@0
    60
	return -1;
slouken@0
    61
}
slouken@0
    62
slouken@0
    63
Uint32 SDL_SemValue(SDL_sem *sem)
slouken@0
    64
{
slouken@0
    65
	return 0;
slouken@0
    66
}
slouken@0
    67
slouken@0
    68
int SDL_SemPost(SDL_sem *sem)
slouken@0
    69
{
slouken@0
    70
	SDL_SetError("SDL not configured with thread support");
slouken@0
    71
	return -1;
slouken@0
    72
}
slouken@0
    73
slouken@0
    74
#else
slouken@0
    75
slouken@0
    76
struct SDL_semaphore
slouken@0
    77
{
slouken@0
    78
	Uint32 count;
slouken@0
    79
	Uint32 waiters_count;
slouken@0
    80
	SDL_mutex *count_lock;
slouken@0
    81
	SDL_cond *count_nonzero;
slouken@0
    82
};
slouken@0
    83
slouken@0
    84
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
slouken@0
    85
{
slouken@0
    86
	SDL_sem *sem;
slouken@0
    87
slouken@0
    88
	sem = (SDL_sem *)malloc(sizeof(*sem));
slouken@0
    89
	if ( ! sem ) {
slouken@0
    90
		SDL_OutOfMemory();
slouken@0
    91
		return(0);
slouken@0
    92
	}
slouken@0
    93
	sem->count = initial_value;
slouken@0
    94
	sem->waiters_count = 0;
slouken@0
    95
slouken@0
    96
	sem->count_lock = SDL_CreateMutex();
slouken@0
    97
	sem->count_nonzero = SDL_CreateCond();
slouken@0
    98
	if ( ! sem->count_lock || ! sem->count_nonzero ) {
slouken@0
    99
		SDL_DestroySemaphore(sem);
slouken@0
   100
		return(0);
slouken@0
   101
	}
slouken@0
   102
slouken@0
   103
	return(sem);
slouken@0
   104
}
slouken@0
   105
slouken@0
   106
/* WARNING:
slouken@0
   107
   You cannot call this function when another thread is using the semaphore.
slouken@0
   108
*/
slouken@0
   109
void SDL_DestroySemaphore(SDL_sem *sem)
slouken@0
   110
{
slouken@0
   111
	if ( sem ) {
slouken@0
   112
		sem->count = 0xFFFFFFFF;
slouken@0
   113
		while ( sem->waiters_count > 0) {
slouken@0
   114
			SDL_CondSignal(sem->count_nonzero);
slouken@0
   115
			SDL_Delay(10);
slouken@0
   116
		}
slouken@0
   117
		SDL_DestroyCond(sem->count_nonzero);
slouken@0
   118
		SDL_mutexP(sem->count_lock);
slouken@0
   119
		SDL_mutexV(sem->count_lock);
slouken@0
   120
		SDL_DestroyMutex(sem->count_lock);
slouken@0
   121
		free(sem);
slouken@0
   122
	}
slouken@0
   123
}
slouken@0
   124
slouken@0
   125
int SDL_SemTryWait(SDL_sem *sem)
slouken@0
   126
{
slouken@0
   127
	int retval;
slouken@0
   128
slouken@0
   129
	if ( ! sem ) {
slouken@0
   130
		SDL_SetError("Passed a NULL semaphore");
slouken@0
   131
		return -1;
slouken@0
   132
	}
slouken@0
   133
slouken@0
   134
	retval = SDL_MUTEX_TIMEDOUT;
slouken@0
   135
	SDL_LockMutex(sem->count_lock);
slouken@0
   136
	if ( sem->count > 0 ) {
slouken@0
   137
		--sem->count;
slouken@0
   138
		retval = 0;
slouken@0
   139
	}
slouken@0
   140
	SDL_UnlockMutex(sem->count_lock);
slouken@0
   141
slouken@0
   142
	return retval;
slouken@0
   143
}
slouken@0
   144
slouken@0
   145
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
slouken@0
   146
{
slouken@0
   147
	int retval;
slouken@0
   148
slouken@0
   149
	if ( ! sem ) {
slouken@0
   150
		SDL_SetError("Passed a NULL semaphore");
slouken@0
   151
		return -1;
slouken@0
   152
	}
slouken@0
   153
slouken@0
   154
	/* A timeout of 0 is an easy case */
slouken@0
   155
	if ( timeout == 0 ) {
slouken@0
   156
		return SDL_SemTryWait(sem);
slouken@0
   157
	}
slouken@0
   158
slouken@0
   159
	SDL_LockMutex(sem->count_lock);
slouken@0
   160
	++sem->waiters_count;
slouken@0
   161
	retval = 0;
slouken@0
   162
	while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) {
slouken@0
   163
		retval = SDL_CondWaitTimeout(sem->count_nonzero,
slouken@0
   164
		                             sem->count_lock, timeout);
slouken@0
   165
	}
slouken@0
   166
	--sem->waiters_count;
slouken@0
   167
	--sem->count;
slouken@0
   168
	SDL_UnlockMutex(sem->count_lock);
slouken@0
   169
slouken@0
   170
	return retval;
slouken@0
   171
}
slouken@0
   172
slouken@0
   173
int SDL_SemWait(SDL_sem *sem)
slouken@0
   174
{
slouken@0
   175
	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
slouken@0
   176
}
slouken@0
   177
slouken@0
   178
Uint32 SDL_SemValue(SDL_sem *sem)
slouken@0
   179
{
slouken@0
   180
	Uint32 value;
slouken@0
   181
	
slouken@0
   182
	value = 0;
slouken@0
   183
	if ( sem ) {
slouken@0
   184
		SDL_LockMutex(sem->count_lock);
slouken@0
   185
		value = sem->count;
slouken@0
   186
		SDL_UnlockMutex(sem->count_lock);
slouken@0
   187
	}
slouken@0
   188
	return value;
slouken@0
   189
}
slouken@0
   190
slouken@0
   191
int SDL_SemPost(SDL_sem *sem)
slouken@0
   192
{
slouken@0
   193
	if ( ! sem ) {
slouken@0
   194
		SDL_SetError("Passed a NULL semaphore");
slouken@0
   195
		return -1;
slouken@0
   196
	}
slouken@0
   197
slouken@0
   198
	SDL_LockMutex(sem->count_lock);
slouken@0
   199
	if ( sem->waiters_count > 0 ) {
slouken@0
   200
		SDL_CondSignal(sem->count_nonzero);
slouken@0
   201
	}
slouken@0
   202
	++sem->count;
slouken@0
   203
	SDL_UnlockMutex(sem->count_lock);
slouken@0
   204
slouken@0
   205
	return 0;
slouken@0
   206
}
slouken@0
   207
slouken@0
   208
#endif /* DISABLE_THREADS */