- Added SDL, libjpeg and libpng
- Added Android project and Java files
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Mutex functions using the Win32 API */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
CRITICAL_SECTION cs;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
/* Allocate mutex memory */
|
||||
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
|
||||
if (mutex) {
|
||||
/* Initialize */
|
||||
#ifdef _WIN32_WCE
|
||||
InitializeCriticalSection(&mutex->cs);
|
||||
#else
|
||||
/* On SMP systems, a non-zero spin count generally helps performance */
|
||||
InitializeCriticalSectionAndSpinCount(&mutex->cs, 2000);
|
||||
#endif
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (mutex);
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex) {
|
||||
DeleteCriticalSection(&mutex->cs);
|
||||
SDL_free(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int
|
||||
SDL_mutexP(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&mutex->cs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int
|
||||
SDL_mutexV(SDL_mutex * mutex)
|
||||
{
|
||||
if (mutex == NULL) {
|
||||
SDL_SetError("Passed a NULL mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&mutex->cs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Semaphore functions using the Win32 API */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
#include "win_ce_semaphore.h"
|
||||
#endif
|
||||
|
||||
|
||||
struct SDL_semaphore
|
||||
{
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
SYNCHHANDLE id;
|
||||
#else
|
||||
HANDLE id;
|
||||
#endif
|
||||
LONG count;
|
||||
};
|
||||
|
||||
|
||||
/* Create a semaphore */
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
SDL_sem *sem;
|
||||
|
||||
/* Allocate sem memory */
|
||||
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
|
||||
if (sem) {
|
||||
/* Create the semaphore, with max value 32K */
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
sem->id = CreateSemaphoreCE(NULL, initial_value, 32 * 1024, NULL);
|
||||
#else
|
||||
sem->id = CreateSemaphore(NULL, initial_value, 32 * 1024, NULL);
|
||||
#endif
|
||||
sem->count = initial_value;
|
||||
if (!sem->id) {
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
SDL_free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (sem);
|
||||
}
|
||||
|
||||
/* Free the semaphore */
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if (sem) {
|
||||
if (sem->id) {
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
CloseSynchHandle(sem->id);
|
||||
#else
|
||||
CloseHandle(sem->id);
|
||||
#endif
|
||||
sem->id = 0;
|
||||
}
|
||||
SDL_free(sem);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
int retval;
|
||||
DWORD dwMilliseconds;
|
||||
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
dwMilliseconds = INFINITE;
|
||||
} else {
|
||||
dwMilliseconds = (DWORD) timeout;
|
||||
}
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
|
||||
#else
|
||||
switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
|
||||
#endif
|
||||
case WAIT_OBJECT_0:
|
||||
InterlockedDecrement(&sem->count);
|
||||
retval = 0;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("WaitForSingleObject() failed");
|
||||
retval = -1;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, 0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
|
||||
}
|
||||
|
||||
/* Returns the current count of the semaphore */
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return 0;
|
||||
}
|
||||
return (Uint32)sem->count;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
if (!sem) {
|
||||
SDL_SetError("Passed a NULL sem");
|
||||
return -1;
|
||||
}
|
||||
/* Increase the counter in the first place, because
|
||||
* after a successful release the semaphore may
|
||||
* immediately get destroyed by another thread which
|
||||
* is waiting for this semaphore.
|
||||
*/
|
||||
InterlockedIncrement(&sem->count);
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
if (ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE) {
|
||||
#else
|
||||
if (ReleaseSemaphore(sem->id, 1, NULL) == FALSE) {
|
||||
#endif
|
||||
InterlockedDecrement(&sem->count); /* restore */
|
||||
SDL_SetError("ReleaseSemaphore() failed");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Win32 thread management routines for SDL */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "../SDL_systhread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
|
||||
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
#ifndef _WIN32_WCE
|
||||
/* We'll use the C library from this DLL */
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#if __GNUC__
|
||||
typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void *),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#elif defined(__WATCOMC__)
|
||||
/* This is for Watcom targets except OS2 */
|
||||
#if __WATCOMC__ < 1240
|
||||
#define __watcall
|
||||
#endif
|
||||
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
|
||||
unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#else
|
||||
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned (__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg, unsigned,
|
||||
unsigned *threadID);
|
||||
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#endif
|
||||
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
|
||||
|
||||
typedef struct ThreadStartParms
|
||||
{
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
} tThreadStartParms, *pThreadStartParms;
|
||||
|
||||
static DWORD __stdcall
|
||||
RunThread(void *data)
|
||||
{
|
||||
pThreadStartParms pThreadParms = (pThreadStartParms) data;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL;
|
||||
|
||||
// Call the thread function!
|
||||
SDL_RunThread(pThreadParms->args);
|
||||
|
||||
// Get the current endthread we have to use!
|
||||
if (pThreadParms) {
|
||||
pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread;
|
||||
SDL_free(pThreadParms);
|
||||
}
|
||||
// Call endthread!
|
||||
if (pfnCurrentEndThread)
|
||||
(*pfnCurrentEndThread) (0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread)
|
||||
{
|
||||
#else
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = NULL;
|
||||
#else
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = _endthreadex;
|
||||
#endif
|
||||
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
unsigned threadid;
|
||||
pThreadStartParms pThreadParms =
|
||||
(pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
|
||||
if (!pThreadParms) {
|
||||
SDL_OutOfMemory();
|
||||
return (-1);
|
||||
}
|
||||
// Save the function which we will have to call to clear the RTL of calling app!
|
||||
pThreadParms->pfnCurrentEndThread = pfnEndThread;
|
||||
// Also save the real parameters we have to pass to thread function
|
||||
pThreadParms->args = args;
|
||||
|
||||
if (pfnBeginThread) {
|
||||
thread->handle =
|
||||
(SYS_ThreadHandle) pfnBeginThread(NULL, 0, RunThread,
|
||||
pThreadParms, 0, &threadid);
|
||||
} else {
|
||||
thread->handle =
|
||||
CreateThread(NULL, 0, RunThread, pThreadParms, 0, &threadid);
|
||||
}
|
||||
if (thread->handle == NULL) {
|
||||
SDL_SetError("Not enough resources to create thread");
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
return ((SDL_threadID) GetCurrentThreadId());
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
int value;
|
||||
|
||||
if (priority == SDL_THREAD_PRIORITY_LOW) {
|
||||
value = THREAD_PRIORITY_LOWEST;
|
||||
} else if (priority == SDL_THREAD_PRIORITY_HIGH) {
|
||||
value = THREAD_PRIORITY_HIGHEST;
|
||||
} else {
|
||||
value = THREAD_PRIORITY_NORMAL;
|
||||
}
|
||||
if (!SetThreadPriority(GetCurrentThread(), value)) {
|
||||
WIN_SetError("SetThreadPriority()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
WaitForSingleObject(thread->handle, INFINITE);
|
||||
CloseHandle(thread->handle);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_systhread_c_h
|
||||
#define _SDL_systhread_c_h
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
typedef HANDLE SYS_ThreadHandle;
|
||||
|
||||
#endif /* _SDL_systhread_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,227 @@
|
||||
/* win_ce_semaphore.c
|
||||
|
||||
Copyright (c) 1998, Johnson M. Hart
|
||||
(with corrections 2001 by Rainer Loritz)
|
||||
Permission is granted for any and all use providing that this
|
||||
copyright is properly acknowledged.
|
||||
There are no assurances of suitability for any use whatsoever.
|
||||
|
||||
WINDOWS CE: There is a collection of Windows CE functions to simulate
|
||||
semaphores using only a mutex and an event. As Windows CE events cannot
|
||||
be named, these simulated semaphores cannot be named either.
|
||||
|
||||
Implementation notes:
|
||||
1. All required internal data structures are allocated on the process's heap.
|
||||
2. Where appropriate, a new error code is returned (see the header
|
||||
file), or, if the error is a Win32 error, that code is unchanged.
|
||||
3. Notice the new handle type "SYNCHHANDLE" that has handles, counters,
|
||||
and other information. This structure will grow as new objects are added
|
||||
to this set; some members are specific to only one or two of the objects.
|
||||
4. Mutexes are used for critical sections. These could be replaced with
|
||||
CRITICAL_SECTION objects but then this would give up the time out
|
||||
capability.
|
||||
5. The implementation shows several interesting aspects of synchronization, some
|
||||
of which are specific to Win32 and some of which are general. These are pointed
|
||||
out in the comments as appropriate.
|
||||
6. The wait function emulates WaitForSingleObject only. An emulation of
|
||||
WaitForMultipleObjects is much harder to implement outside the kernel,
|
||||
and it is not clear how to handle a mixture of WCE semaphores and normal
|
||||
events and mutexes. */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include "win_ce_semaphore.h"
|
||||
|
||||
static SYNCHHANDLE CleanUp(SYNCHHANDLE hSynch, DWORD Flags);
|
||||
|
||||
SYNCHHANDLE
|
||||
CreateSemaphoreCE(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */
|
||||
LONG lInitialCount, /* initial count */
|
||||
LONG lMaximumCount, /* maximum count */
|
||||
LPCTSTR lpName)
|
||||
/* Semaphore for use with Windows CE that does not support them directly.
|
||||
Requires a counter, a mutex to protect the counter, and an
|
||||
autoreset event.
|
||||
|
||||
Here are the rules that must always hold between the autoreset event
|
||||
and the mutex (any violation of these rules by the CE semaphore functions
|
||||
will, in all likelihood, result in a defect):
|
||||
1. No thread can set, pulse, or reset the event,
|
||||
nor can it access any part of the SYNCHHANDLE structure,
|
||||
without first gaining ownership of the mutex.
|
||||
BUT, a thread can wait on the event without owning the mutex
|
||||
(this is clearly necessary or else the event could never be set).
|
||||
2. The event is in a signaled state if and only if the current semaphore
|
||||
count ("CurCount") is greater than zero.
|
||||
3. The semaphore count is always >= 0 and <= the maximum count */
|
||||
{
|
||||
SYNCHHANDLE hSynch = NULL, result = NULL;
|
||||
|
||||
__try {
|
||||
if (lInitialCount > lMaximumCount || lMaximumCount < 0
|
||||
|| lInitialCount < 0) {
|
||||
/* Bad parameters */
|
||||
SetLastError(SYNCH_ERROR);
|
||||
__leave;
|
||||
}
|
||||
|
||||
hSynch =
|
||||
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE);
|
||||
if (hSynch == NULL)
|
||||
__leave;
|
||||
|
||||
hSynch->MaxCount = lMaximumCount;
|
||||
hSynch->CurCount = lInitialCount;
|
||||
hSynch->lpName = lpName;
|
||||
|
||||
hSynch->hMutex = CreateMutex(lpSemaphoreAttributes, FALSE, NULL);
|
||||
|
||||
WaitForSingleObject(hSynch->hMutex, INFINITE);
|
||||
/* Create the event. It is initially signaled if and only if the
|
||||
initial count is > 0 */
|
||||
hSynch->hEvent = CreateEvent(lpSemaphoreAttributes, FALSE,
|
||||
lInitialCount > 0, NULL);
|
||||
ReleaseMutex(hSynch->hMutex);
|
||||
hSynch->hSemph = NULL;
|
||||
}
|
||||
__finally {
|
||||
/* Return with the handle, or, if there was any error, return
|
||||
a null after closing any open handles and freeing any allocated memory. */
|
||||
result =
|
||||
CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */ );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL
|
||||
ReleaseSemaphoreCE(SYNCHHANDLE hSemCE, LONG cReleaseCount,
|
||||
LPLONG lpPreviousCount)
|
||||
/* Windows CE equivalent to ReleaseSemaphore. */
|
||||
{
|
||||
BOOL Result = TRUE;
|
||||
|
||||
/* Gain access to the object to assure that the release count
|
||||
would not cause the total count to exceed the maximum. */
|
||||
|
||||
__try {
|
||||
WaitForSingleObject(hSemCE->hMutex, INFINITE);
|
||||
/* reply only if asked to */
|
||||
if (lpPreviousCount != NULL)
|
||||
*lpPreviousCount = hSemCE->CurCount;
|
||||
if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount
|
||||
|| cReleaseCount <= 0) {
|
||||
SetLastError(SYNCH_ERROR);
|
||||
Result = FALSE;
|
||||
__leave;
|
||||
}
|
||||
hSemCE->CurCount += cReleaseCount;
|
||||
|
||||
/* Set the autoreset event, releasing exactly one waiting thread, now or
|
||||
in the future. */
|
||||
|
||||
SetEvent(hSemCE->hEvent);
|
||||
}
|
||||
__finally {
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WaitForSemaphoreCE(SYNCHHANDLE hSemCE, DWORD dwMilliseconds)
|
||||
/* Windows CE semaphore equivalent of WaitForSingleObject. */
|
||||
{
|
||||
DWORD WaitResult;
|
||||
|
||||
WaitResult = WaitForSingleObject(hSemCE->hMutex, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0)
|
||||
return WaitResult;
|
||||
while (hSemCE->CurCount <= 0) {
|
||||
|
||||
/* The count is 0, and the thread must wait on the event (which, by
|
||||
the rules, is currently reset) for semaphore resources to become
|
||||
available. First, of course, the mutex must be released so that another
|
||||
thread will be capable of setting the event. */
|
||||
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
|
||||
/* Wait for the event to be signaled, indicating a semaphore state change.
|
||||
The event is autoreset and signaled with a SetEvent (not PulseEvent)
|
||||
so exactly one waiting thread (whether or not there is currently
|
||||
a waiting thread) is released as a result of the SetEvent. */
|
||||
|
||||
WaitResult = WaitForSingleObject(hSemCE->hEvent, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0)
|
||||
return WaitResult;
|
||||
|
||||
/* This is where the properties of setting of an autoreset event is critical
|
||||
to assure that, even if the semaphore state changes between the
|
||||
preceding Wait and the next, and even if NO threads are waiting
|
||||
on the event at the time of the SetEvent, at least one thread
|
||||
will be released.
|
||||
Pulsing a manual reset event would appear to work, but it would have
|
||||
a defect which could appear if the semaphore state changed between
|
||||
the two waits. */
|
||||
|
||||
WaitResult = WaitForSingleObject(hSemCE->hMutex, dwMilliseconds);
|
||||
if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0)
|
||||
return WaitResult;
|
||||
|
||||
}
|
||||
/* The count is not zero and this thread owns the mutex. */
|
||||
|
||||
hSemCE->CurCount--;
|
||||
/* The event is now unsignaled, BUT, the semaphore count may not be
|
||||
zero, in which case the event should be signaled again
|
||||
before releasing the mutex. */
|
||||
|
||||
if (hSemCE->CurCount > 0)
|
||||
SetEvent(hSemCE->hEvent);
|
||||
ReleaseMutex(hSemCE->hMutex);
|
||||
return WaitResult;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CloseSynchHandle(SYNCHHANDLE hSynch)
|
||||
/* Close a synchronization handle.
|
||||
Improvement: Test for a valid handle before dereferencing the handle. */
|
||||
{
|
||||
BOOL Result = TRUE;
|
||||
if (hSynch->hEvent != NULL)
|
||||
Result = Result && CloseHandle(hSynch->hEvent);
|
||||
if (hSynch->hMutex != NULL)
|
||||
Result = Result && CloseHandle(hSynch->hMutex);
|
||||
if (hSynch->hSemph != NULL)
|
||||
Result = Result && CloseHandle(hSynch->hSemph);
|
||||
HeapFree(GetProcessHeap(), 0, hSynch);
|
||||
return (Result);
|
||||
}
|
||||
|
||||
static SYNCHHANDLE
|
||||
CleanUp(SYNCHHANDLE hSynch, DWORD Flags)
|
||||
{ /* Prepare to return from a create of a synchronization handle.
|
||||
If there was any failure, free any allocated resources.
|
||||
"Flags" indicates which Win32 objects are required in the
|
||||
synchronization handle. */
|
||||
|
||||
BOOL ok = TRUE;
|
||||
|
||||
if (hSynch == NULL)
|
||||
return NULL;
|
||||
if ((Flags & 4) == 1 && (hSynch->hEvent == NULL))
|
||||
ok = FALSE;
|
||||
if ((Flags & 2) == 1 && (hSynch->hMutex == NULL))
|
||||
ok = FALSE;
|
||||
if ((Flags & 1) == 1 && (hSynch->hEvent == NULL))
|
||||
ok = FALSE;
|
||||
if (!ok) {
|
||||
CloseSynchHandle(hSynch);
|
||||
return NULL;
|
||||
}
|
||||
/* Everything worked */
|
||||
return hSynch;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
@@ -0,0 +1,25 @@
|
||||
/* win_ce_semaphore.h - header file to go with win_ce_semaphore.c */
|
||||
|
||||
typedef struct _SYNCH_HANDLE_STRUCTURE
|
||||
{
|
||||
HANDLE hEvent;
|
||||
HANDLE hMutex;
|
||||
HANDLE hSemph;
|
||||
LONG MaxCount;
|
||||
volatile LONG CurCount;
|
||||
LPCTSTR lpName;
|
||||
} SYNCH_HANDLE_STRUCTURE, *SYNCHHANDLE;
|
||||
|
||||
#define SYNCH_HANDLE_SIZE sizeof (SYNCH_HANDLE_STRUCTURE)
|
||||
|
||||
/* Error codes - all must have bit 29 set */
|
||||
#define SYNCH_ERROR 0X20000000 /* EXERCISE - REFINE THE ERROR NUMBERS */
|
||||
|
||||
extern SYNCHHANDLE CreateSemaphoreCE(LPSECURITY_ATTRIBUTES, LONG, LONG,
|
||||
LPCTSTR);
|
||||
|
||||
extern BOOL ReleaseSemaphoreCE(SYNCHHANDLE, LONG, LPLONG);
|
||||
extern DWORD WaitForSemaphoreCE(SYNCHHANDLE, DWORD);
|
||||
|
||||
extern BOOL CloseSynchHandle(SYNCHHANDLE);
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
Reference in New Issue
Block a user