/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_syscond.c |
---|
0,0 → 1,222 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_syscond.c |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/* An implementation of condition variables using semaphores and mutexes */ |
/* |
This implementation borrows heavily from the BeOS condition variable |
implementation, written by Christopher Tate and Owen Smith. Thanks! |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include "SDL_error.h" |
#include "SDL_thread.h" |
struct SDL_cond |
{ |
SDL_mutex *lock; |
int waiting; |
int signals; |
SDL_sem *wait_sem; |
SDL_sem *wait_done; |
}; |
/* Create a condition variable */ |
SDL_cond * SDL_CreateCond(void) |
{ |
SDL_cond *cond; |
cond = (SDL_cond *) malloc(sizeof(SDL_cond)); |
if ( cond ) { |
cond->lock = SDL_CreateMutex(); |
cond->wait_sem = SDL_CreateSemaphore(0); |
cond->wait_done = SDL_CreateSemaphore(0); |
cond->waiting = cond->signals = 0; |
if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { |
SDL_DestroyCond(cond); |
cond = NULL; |
} |
} else { |
SDL_OutOfMemory(); |
} |
return(cond); |
} |
/* Destroy a condition variable */ |
void SDL_DestroyCond(SDL_cond *cond) |
{ |
if ( cond ) { |
if ( cond->wait_sem ) { |
SDL_DestroySemaphore(cond->wait_sem); |
} |
if ( cond->wait_done ) { |
SDL_DestroySemaphore(cond->wait_done); |
} |
if ( cond->lock ) { |
SDL_DestroyMutex(cond->lock); |
} |
free(cond); |
} |
} |
/* Restart one of the threads that are waiting on the condition variable */ |
int SDL_CondSignal(SDL_cond *cond) |
{ |
if ( ! cond ) { |
SDL_SetError("Passed a NULL condition variable"); |
return -1; |
} |
/* If there are waiting threads not already signalled, then |
signal the condition and wait for the thread to respond. |
*/ |
SDL_LockMutex(cond->lock); |
if ( cond->waiting > cond->signals ) { |
++cond->signals; |
SDL_SemPost(cond->wait_sem); |
SDL_UnlockMutex(cond->lock); |
SDL_SemWait(cond->wait_done); |
} else { |
SDL_UnlockMutex(cond->lock); |
} |
return 0; |
} |
/* Restart all threads that are waiting on the condition variable */ |
int SDL_CondBroadcast(SDL_cond *cond) |
{ |
if ( ! cond ) { |
SDL_SetError("Passed a NULL condition variable"); |
return -1; |
} |
/* If there are waiting threads not already signalled, then |
signal the condition and wait for the thread to respond. |
*/ |
SDL_LockMutex(cond->lock); |
if ( cond->waiting > cond->signals ) { |
int i, num_waiting; |
num_waiting = (cond->waiting - cond->signals); |
cond->signals = cond->waiting; |
for ( i=0; i<num_waiting; ++i ) { |
SDL_SemPost(cond->wait_sem); |
} |
/* Now all released threads are blocked here, waiting for us. |
Collect them all (and win fabulous prizes!) :-) |
*/ |
SDL_UnlockMutex(cond->lock); |
for ( i=0; i<num_waiting; ++i ) { |
SDL_SemWait(cond->wait_done); |
} |
} else { |
SDL_UnlockMutex(cond->lock); |
} |
return 0; |
} |
/* Wait on the condition variable for at most 'ms' milliseconds. |
The mutex must be locked before entering this function! |
The mutex is unlocked during the wait, and locked again after the wait. |
Typical use: |
Thread A: |
SDL_LockMutex(lock); |
while ( ! condition ) { |
SDL_CondWait(cond); |
} |
SDL_UnlockMutex(lock); |
Thread B: |
SDL_LockMutex(lock); |
... |
condition = true; |
... |
SDL_UnlockMutex(lock); |
*/ |
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) |
{ |
int retval; |
if ( ! cond ) { |
SDL_SetError("Passed a NULL condition variable"); |
return -1; |
} |
/* Obtain the protection mutex, and increment the number of waiters. |
This allows the signal mechanism to only perform a signal if there |
are waiting threads. |
*/ |
SDL_LockMutex(cond->lock); |
++cond->waiting; |
SDL_UnlockMutex(cond->lock); |
/* Unlock the mutex, as is required by condition variable semantics */ |
SDL_UnlockMutex(mutex); |
/* Wait for a signal */ |
if ( ms == SDL_MUTEX_MAXWAIT ) { |
retval = SDL_SemWait(cond->wait_sem); |
} else { |
retval = SDL_SemWaitTimeout(cond->wait_sem, ms); |
} |
/* Let the signaler know we have completed the wait, otherwise |
the signaler can race ahead and get the condition semaphore |
if we are stopped between the mutex unlock and semaphore wait, |
giving a deadlock. See the following URL for details: |
http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html |
*/ |
SDL_LockMutex(cond->lock); |
if ( cond->signals > 0 ) { |
/* If we timed out, we need to eat a condition signal */ |
if ( retval > 0 ) { |
SDL_SemWait(cond->wait_sem); |
} |
/* We always notify the signal thread that we are done */ |
SDL_SemPost(cond->wait_done); |
/* Signal handshake complete */ |
--cond->signals; |
} |
--cond->waiting; |
SDL_UnlockMutex(cond->lock); |
/* Lock the mutex, as is required by condition variable semantics */ |
SDL_LockMutex(mutex); |
return retval; |
} |
/* Wait on the condition variable forever */ |
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) |
{ |
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); |
} |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_syscond_c.h |
---|
0,0 → 1,25 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_syscond_c.h |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_sysmutex.c |
---|
0,0 → 1,136 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_sysmutex.c |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/* An implementation of mutexes using semaphores */ |
#include <stdio.h> |
#include <stdlib.h> |
#include "SDL_error.h" |
#include "SDL_thread.h" |
#include "SDL_systhread_c.h" |
struct SDL_mutex { |
int recursive; |
Uint32 owner; |
SDL_sem *sem; |
}; |
/* Create a mutex */ |
SDL_mutex *SDL_CreateMutex(void) |
{ |
SDL_mutex *mutex; |
/* Allocate mutex memory */ |
mutex = (SDL_mutex *)malloc(sizeof(*mutex)); |
if ( mutex ) { |
/* Create the mutex semaphore, with initial value 1 */ |
mutex->sem = SDL_CreateSemaphore(1); |
mutex->recursive = 0; |
mutex->owner = 0; |
if ( ! mutex->sem ) { |
free(mutex); |
mutex = NULL; |
} |
} else { |
SDL_OutOfMemory(); |
} |
return mutex; |
} |
/* Free the mutex */ |
void SDL_DestroyMutex(SDL_mutex *mutex) |
{ |
if ( mutex ) { |
if ( mutex->sem ) { |
SDL_DestroySemaphore(mutex->sem); |
} |
free(mutex); |
} |
} |
/* Lock the semaphore */ |
int SDL_mutexP(SDL_mutex *mutex) |
{ |
#ifdef DISABLE_THREADS |
return 0; |
#else |
Uint32 this_thread; |
if ( mutex == NULL ) { |
SDL_SetError("Passed a NULL mutex"); |
return -1; |
} |
this_thread = SDL_ThreadID(); |
if ( mutex->owner == this_thread ) { |
++mutex->recursive; |
} else { |
/* The order of operations is important. |
We set the locking thread id after we obtain the lock |
so unlocks from other threads will fail. |
*/ |
SDL_SemWait(mutex->sem); |
mutex->owner = this_thread; |
mutex->recursive = 0; |
} |
return 0; |
#endif /* DISABLE_THREADS */ |
} |
/* Unlock the mutex */ |
int SDL_mutexV(SDL_mutex *mutex) |
{ |
#ifdef DISABLE_THREADS |
return 0; |
#else |
if ( mutex == NULL ) { |
SDL_SetError("Passed a NULL mutex"); |
return -1; |
} |
/* If we don't own the mutex, we can't unlock it */ |
if ( SDL_ThreadID() != mutex->owner ) { |
SDL_SetError("mutex not owned by this thread"); |
return -1; |
} |
if ( mutex->recursive ) { |
--mutex->recursive; |
} else { |
/* The order of operations is important. |
First reset the owner so another thread doesn't lock |
the mutex and set the ownership before we reset it, |
then release the lock semaphore. |
*/ |
mutex->owner = 0; |
SDL_SemPost(mutex->sem); |
} |
return 0; |
#endif /* DISABLE_THREADS */ |
} |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_sysmutex_c.h |
---|
0,0 → 1,25 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_sysmutex_c.h |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_syssem.c |
---|
0,0 → 1,213 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_syssem.c |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/* An implementation of semaphores using mutexes and condition variables */ |
#include <stdlib.h> |
#include "SDL_error.h" |
#include "SDL_timer.h" |
#include "SDL_thread.h" |
#include "SDL_systhread_c.h" |
#ifdef DISABLE_THREADS |
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) |
{ |
SDL_SetError("SDL not configured with thread support"); |
return (SDL_sem *)0; |
} |
void SDL_DestroySemaphore(SDL_sem *sem) |
{ |
return; |
} |
int SDL_SemTryWait(SDL_sem *sem) |
{ |
SDL_SetError("SDL not configured with thread support"); |
return -1; |
} |
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) |
{ |
SDL_SetError("SDL not configured with thread support"); |
return -1; |
} |
int SDL_SemWait(SDL_sem *sem) |
{ |
SDL_SetError("SDL not configured with thread support"); |
return -1; |
} |
Uint32 SDL_SemValue(SDL_sem *sem) |
{ |
return 0; |
} |
int SDL_SemPost(SDL_sem *sem) |
{ |
SDL_SetError("SDL not configured with thread support"); |
return -1; |
} |
#else |
struct SDL_semaphore |
{ |
Uint32 count; |
Uint32 waiters_count; |
SDL_mutex *count_lock; |
SDL_cond *count_nonzero; |
}; |
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) |
{ |
SDL_sem *sem; |
sem = (SDL_sem *)malloc(sizeof(*sem)); |
if ( ! sem ) { |
SDL_OutOfMemory(); |
return(0); |
} |
sem->count = initial_value; |
sem->waiters_count = 0; |
sem->count_lock = SDL_CreateMutex(); |
sem->count_nonzero = SDL_CreateCond(); |
if ( ! sem->count_lock || ! sem->count_nonzero ) { |
SDL_DestroySemaphore(sem); |
return(0); |
} |
return(sem); |
} |
/* WARNING: |
You cannot call this function when another thread is using the semaphore. |
*/ |
void SDL_DestroySemaphore(SDL_sem *sem) |
{ |
if ( sem ) { |
sem->count = 0xFFFFFFFF; |
while ( sem->waiters_count > 0) { |
SDL_CondSignal(sem->count_nonzero); |
SDL_Delay(10); |
} |
SDL_DestroyCond(sem->count_nonzero); |
SDL_mutexP(sem->count_lock); |
SDL_mutexV(sem->count_lock); |
SDL_DestroyMutex(sem->count_lock); |
free(sem); |
} |
} |
int SDL_SemTryWait(SDL_sem *sem) |
{ |
int retval; |
if ( ! sem ) { |
SDL_SetError("Passed a NULL semaphore"); |
return -1; |
} |
retval = SDL_MUTEX_TIMEDOUT; |
SDL_LockMutex(sem->count_lock); |
if ( sem->count > 0 ) { |
--sem->count; |
retval = 0; |
} |
SDL_UnlockMutex(sem->count_lock); |
return retval; |
} |
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) |
{ |
int retval; |
if ( ! sem ) { |
SDL_SetError("Passed a NULL semaphore"); |
return -1; |
} |
/* A timeout of 0 is an easy case */ |
if ( timeout == 0 ) { |
return SDL_SemTryWait(sem); |
} |
SDL_LockMutex(sem->count_lock); |
++sem->waiters_count; |
retval = 0; |
while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) { |
retval = SDL_CondWaitTimeout(sem->count_nonzero, |
sem->count_lock, timeout); |
} |
--sem->waiters_count; |
--sem->count; |
SDL_UnlockMutex(sem->count_lock); |
return retval; |
} |
int SDL_SemWait(SDL_sem *sem) |
{ |
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); |
} |
Uint32 SDL_SemValue(SDL_sem *sem) |
{ |
Uint32 value; |
value = 0; |
if ( sem ) { |
SDL_LockMutex(sem->count_lock); |
value = sem->count; |
SDL_UnlockMutex(sem->count_lock); |
} |
return value; |
} |
int SDL_SemPost(SDL_sem *sem) |
{ |
if ( ! sem ) { |
SDL_SetError("Passed a NULL semaphore"); |
return -1; |
} |
SDL_LockMutex(sem->count_lock); |
if ( sem->waiters_count > 0 ) { |
SDL_CondSignal(sem->count_nonzero); |
} |
++sem->count; |
SDL_UnlockMutex(sem->count_lock); |
return 0; |
} |
#endif /* DISABLE_THREADS */ |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_syssem_c.h |
---|
0,0 → 1,25 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_syssem_c.h |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_systhread.c |
---|
0,0 → 1,58 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_systhread.c |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/* Thread management routines for SDL */ |
#include "SDL_error.h" |
#include "SDL_thread.h" |
#include "SDL_systhread.h" |
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) |
{ |
SDL_SetError("Threads are not supported on this platform"); |
return(-1); |
} |
void SDL_SYS_SetupThread(void) |
{ |
return; |
} |
Uint32 SDL_ThreadID(void) |
{ |
return(0); |
} |
void SDL_SYS_WaitThread(SDL_Thread *thread) |
{ |
return; |
} |
void SDL_SYS_KillThread(SDL_Thread *thread) |
{ |
return; |
} |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_systhread.h |
---|
0,0 → 1,48 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
#ifdef SAVE_RCSID |
static char rcsid = |
"@(#) $Id: SDL_systhread.h,v 1.2 2001/04/26 16:50:17 hercules Exp $"; |
#endif |
/* These are functions that need to be implemented by a port of SDL */ |
#include "SDL_thread_c.h" |
/* This function creates a thread, passing args to SDL_RunThread(), |
saves a system-dependent thread id in thread->id, and returns 0 |
on success. |
*/ |
extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args); |
/* This function does any necessary setup in the child thread */ |
extern void SDL_SYS_SetupThread(void); |
/* This function waits for the thread to finish and frees any data |
allocated by SDL_SYS_CreateThread() |
*/ |
extern void SDL_SYS_WaitThread(SDL_Thread *thread); |
/* This function kills the thread and returns */ |
extern void SDL_SYS_KillThread(SDL_Thread *thread); |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_systhread_c.h |
---|
0,0 → 1,29 |
/* WARNING: This file was automatically generated! |
* Original: ./src/thread/generic/SDL_systhread_c.h |
*/ |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/* Stub until we implement threads on this platform */ |
typedef int SYS_ThreadHandle; |
#define DISABLE_THREADS |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_thread.c |
---|
0,0 → 1,296 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
/* System independent thread management routines for SDL */ |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include "SDL_error.h" |
#include "SDL_mutex.h" |
#include "SDL_thread.h" |
#include "SDL_thread_c.h" |
#include "SDL_systhread.h" |
#define ARRAY_CHUNKSIZE 32 |
/* The array of threads currently active in the application |
(except the main thread) |
The manipulation of an array here is safer than using a linked list. |
*/ |
static int SDL_maxthreads = 0; |
static int SDL_numthreads = 0; |
static SDL_Thread **SDL_Threads = NULL; |
static SDL_mutex *thread_lock = NULL; |
int _creating_thread_lock = 0; |
int SDL_ThreadsInit(void) |
{ |
int retval; |
retval = 0; |
/* Set the thread lock creation flag so that we can reuse an |
existing lock on the system - since this mutex never gets |
destroyed (see SDL_ThreadsQuit()), we want to reuse it. |
*/ |
_creating_thread_lock = 1; |
thread_lock = SDL_CreateMutex(); |
_creating_thread_lock = 0; |
if ( thread_lock == NULL ) { |
retval = -1; |
} |
return(retval); |
} |
/* This should never be called... |
If this is called by SDL_Quit(), we don't know whether or not we should |
clean up threads here. If any threads are still running after this call, |
they will no longer have access to any per-thread data. |
*/ |
void SDL_ThreadsQuit() |
{ |
SDL_mutex *mutex; |
mutex = thread_lock; |
thread_lock = NULL; |
if ( mutex != NULL ) { |
SDL_DestroyMutex(mutex); |
} |
} |
/* Routines for manipulating the thread list */ |
static void SDL_AddThread(SDL_Thread *thread) |
{ |
SDL_Thread **threads; |
/* WARNING: |
If the very first threads are created simultaneously, then |
there could be a race condition causing memory corruption. |
In practice, this isn't a problem because by definition there |
is only one thread running the first time this is called. |
*/ |
if ( thread_lock == NULL ) { |
if ( SDL_ThreadsInit() < 0 ) { |
return; |
} |
} |
SDL_mutexP(thread_lock); |
/* Expand the list of threads, if necessary */ |
#ifdef DEBUG_THREADS |
printf("Adding thread (%d already - %d max)\n", |
SDL_numthreads, SDL_maxthreads); |
#endif |
if ( SDL_numthreads == SDL_maxthreads ) { |
threads=(SDL_Thread **)malloc((SDL_maxthreads+ARRAY_CHUNKSIZE)* |
(sizeof *threads)); |
if ( threads == NULL ) { |
SDL_OutOfMemory(); |
goto done; |
} |
memcpy(threads, SDL_Threads, SDL_numthreads*(sizeof *threads)); |
SDL_maxthreads += ARRAY_CHUNKSIZE; |
if ( SDL_Threads ) { |
free(SDL_Threads); |
} |
SDL_Threads = threads; |
} |
SDL_Threads[SDL_numthreads++] = thread; |
done: |
SDL_mutexV(thread_lock); |
} |
static void SDL_DelThread(SDL_Thread *thread) |
{ |
int i; |
if ( thread_lock ) { |
SDL_mutexP(thread_lock); |
for ( i=0; i<SDL_numthreads; ++i ) { |
if ( thread == SDL_Threads[i] ) { |
break; |
} |
} |
if ( i < SDL_numthreads ) { |
--SDL_numthreads; |
while ( i < SDL_numthreads ) { |
SDL_Threads[i] = SDL_Threads[i+1]; |
++i; |
} |
#ifdef DEBUG_THREADS |
printf("Deleting thread (%d left - %d max)\n", |
SDL_numthreads, SDL_maxthreads); |
#endif |
} |
SDL_mutexV(thread_lock); |
} |
} |
/* The default (non-thread-safe) global error variable */ |
static SDL_error SDL_global_error; |
/* Routine to get the thread-specific error variable */ |
SDL_error *SDL_GetErrBuf(void) |
{ |
SDL_error *errbuf; |
errbuf = &SDL_global_error; |
if ( SDL_Threads ) { |
int i; |
Uint32 this_thread; |
this_thread = SDL_ThreadID(); |
SDL_mutexP(thread_lock); |
for ( i=0; i<SDL_numthreads; ++i ) { |
if ( this_thread == SDL_Threads[i]->threadid ) { |
errbuf = &SDL_Threads[i]->errbuf; |
break; |
} |
} |
SDL_mutexV(thread_lock); |
} |
return(errbuf); |
} |
/* Arguments and callback to setup and run the user thread function */ |
typedef struct { |
int (*func)(void *); |
void *data; |
SDL_Thread *info; |
SDL_sem *wait; |
} thread_args; |
void SDL_RunThread(void *data) |
{ |
thread_args *args; |
int (*userfunc)(void *); |
void *userdata; |
int *statusloc; |
/* Perform any system-dependent setup |
- this function cannot fail, and cannot use SDL_SetError() |
*/ |
SDL_SYS_SetupThread(); |
/* Get the thread id */ |
args = (thread_args *)data; |
args->info->threadid = SDL_ThreadID(); |
/* Figure out what function to run */ |
userfunc = args->func; |
userdata = args->data; |
statusloc = &args->info->status; |
/* Wake up the parent thread */ |
SDL_SemPost(args->wait); |
/* Run the function */ |
*statusloc = userfunc(userdata); |
} |
SDL_Thread *SDL_CreateThread(int (*fn)(void *), void *data) |
{ |
SDL_Thread *thread; |
thread_args *args; |
int ret; |
/* Allocate memory for the thread info structure */ |
thread = (SDL_Thread *)malloc(sizeof(*thread)); |
if ( thread == NULL ) { |
SDL_OutOfMemory(); |
return(NULL); |
} |
memset(thread, 0, (sizeof *thread)); |
thread->status = -1; |
/* Set up the arguments for the thread */ |
args = (thread_args *)malloc(sizeof(*args)); |
if ( args == NULL ) { |
SDL_OutOfMemory(); |
free(thread); |
return(NULL); |
} |
args->func = fn; |
args->data = data; |
args->info = thread; |
args->wait = SDL_CreateSemaphore(0); |
if ( args->wait == NULL ) { |
free(thread); |
free(args); |
return(NULL); |
} |
/* Add the thread to the list of available threads */ |
SDL_AddThread(thread); |
/* Create the thread and go! */ |
ret = SDL_SYS_CreateThread(thread, args); |
if ( ret >= 0 ) { |
/* Wait for the thread function to use arguments */ |
SDL_SemWait(args->wait); |
} else { |
/* Oops, failed. Gotta free everything */ |
SDL_DelThread(thread); |
free(thread); |
thread = NULL; |
} |
SDL_DestroySemaphore(args->wait); |
free(args); |
/* Everything is running now */ |
return(thread); |
} |
void SDL_WaitThread(SDL_Thread *thread, int *status) |
{ |
if ( thread ) { |
SDL_SYS_WaitThread(thread); |
if ( status ) { |
*status = thread->status; |
} |
SDL_DelThread(thread); |
free(thread); |
} |
} |
Uint32 SDL_GetThreadID(SDL_Thread *thread) |
{ |
Uint32 id; |
if ( thread ) { |
id = thread->threadid; |
} else { |
id = SDL_ThreadID(); |
} |
return(id); |
} |
void SDL_KillThread(SDL_Thread *thread) |
{ |
if ( thread ) { |
SDL_SYS_KillThread(thread); |
SDL_WaitThread(thread, NULL); |
} |
} |
/contrib/sdk/sources/SDL-1.2.2/src/thread/SDL_thread_c.h |
---|
0,0 → 1,44 |
/* |
SDL - Simple DirectMedia Layer |
Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com |
*/ |
#ifndef _SDL_thread_c_h |
#define _SDL_thread_c_h |
#include "SDL_error_c.h" |
#include "SDL_systhread_c.h" |
/* This is the system-independent thread info structure */ |
struct SDL_Thread { |
Uint32 threadid; |
SYS_ThreadHandle handle; |
int status; |
SDL_error errbuf; |
void *data; |
}; |
/* This is the function called to run a thread */ |
extern void SDL_RunThread(void *data); |
/* Routine to get the thread-specific error variable */ |
extern SDL_error *SDL_GetErrBuf(void); |
#endif /* _SDL_thread_c_h */ |