mirror of
https://github.com/id-Software/RTCW-MP.git
synced 2026-03-20 00:49:40 +01:00
1529 lines
40 KiB
C
1529 lines
40 KiB
C
/*
|
||
===========================================================================
|
||
|
||
Return to Castle Wolfenstein multiplayer GPL Source Code
|
||
Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
|
||
|
||
This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
|
||
|
||
RTCW MP Source Code is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
RTCW MP Source Code 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 General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
|
||
|
||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||
|
||
===========================================================================
|
||
*/
|
||
|
||
//===========================================================================
|
||
//
|
||
// Name: l_threads.c
|
||
// Function: multi-threading
|
||
// Programmer: Mr Elusive (MrElusive@demigod.demon.nl)
|
||
// Last update: 1999-05-14
|
||
// Tab Size: 3
|
||
//===========================================================================
|
||
|
||
#include "l_cmd.h"
|
||
#include "l_threads.h"
|
||
#include "l_log.h"
|
||
#include "l_mem.h"
|
||
|
||
#define MAX_THREADS 64
|
||
|
||
//#define THREAD_DEBUG
|
||
|
||
int dispatch;
|
||
int workcount;
|
||
int oldf;
|
||
qboolean pacifier;
|
||
qboolean threaded;
|
||
void ( *workfunction )( int );
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int GetThreadWork( void ) {
|
||
int r;
|
||
int f;
|
||
|
||
ThreadLock();
|
||
|
||
if ( dispatch == workcount ) {
|
||
ThreadUnlock();
|
||
return -1;
|
||
}
|
||
|
||
f = 10 * dispatch / workcount;
|
||
if ( f != oldf ) {
|
||
oldf = f;
|
||
if ( pacifier ) {
|
||
printf( "%i...", f );
|
||
}
|
||
} //end if
|
||
|
||
r = dispatch;
|
||
dispatch++;
|
||
ThreadUnlock();
|
||
|
||
return r;
|
||
} //end of the function GetThreadWork
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadWorkerFunction( int threadnum ) {
|
||
int work;
|
||
|
||
while ( 1 )
|
||
{
|
||
work = GetThreadWork();
|
||
if ( work == -1 ) {
|
||
break;
|
||
}
|
||
//printf ("thread %i, work %i\n", threadnum, work);
|
||
workfunction( work );
|
||
} //end while
|
||
} //end of the function ThreadWorkerFunction
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )(int) ) {
|
||
if ( numthreads == -1 ) {
|
||
ThreadSetDefault();
|
||
}
|
||
workfunction = func;
|
||
RunThreadsOn( workcnt, showpacifier, ThreadWorkerFunction );
|
||
} //end of the function RunThreadsOnIndividual
|
||
|
||
|
||
//===================================================================
|
||
//
|
||
// WIN32
|
||
//
|
||
//===================================================================
|
||
|
||
#if defined( WIN32 ) || defined( _WIN32 )
|
||
|
||
#define USED
|
||
|
||
#include <windows.h>
|
||
|
||
typedef struct thread_s
|
||
{
|
||
HANDLE handle;
|
||
int threadid;
|
||
int id;
|
||
struct thread_s *next;
|
||
} thread_t;
|
||
|
||
thread_t *firstthread;
|
||
thread_t *lastthread;
|
||
int currentnumthreads;
|
||
int currentthreadid;
|
||
|
||
int numthreads = 1;
|
||
CRITICAL_SECTION crit;
|
||
HANDLE semaphore;
|
||
static int enter;
|
||
static int numwaitingthreads = 0;
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetDefault( void ) {
|
||
SYSTEM_INFO info;
|
||
|
||
if ( numthreads == -1 ) { // not set manually
|
||
GetSystemInfo( &info );
|
||
numthreads = info.dwNumberOfProcessors;
|
||
if ( numthreads < 1 || numthreads > 32 ) {
|
||
numthreads = 1;
|
||
}
|
||
} //end if
|
||
qprintf( "%i threads\n", numthreads );
|
||
} //end of the function ThreadSetDefault
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadLock( void ) {
|
||
if ( !threaded ) {
|
||
Error( "ThreadLock: !threaded" );
|
||
return;
|
||
} //end if
|
||
EnterCriticalSection( &crit );
|
||
if ( enter ) {
|
||
Error( "Recursive ThreadLock\n" );
|
||
}
|
||
enter = 1;
|
||
} //end of the function ThreadLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadUnlock( void ) {
|
||
if ( !threaded ) {
|
||
Error( "ThreadUnlock: !threaded" );
|
||
return;
|
||
} //end if
|
||
if ( !enter ) {
|
||
Error( "ThreadUnlock without lock\n" );
|
||
}
|
||
enter = 0;
|
||
LeaveCriticalSection( &crit );
|
||
} //end of the function ThreadUnlock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupLock( void ) {
|
||
Log_Print( "Win32 multi-threading\n" );
|
||
InitializeCriticalSection( &crit );
|
||
threaded = true; //Stupid me... forgot this!!!
|
||
currentnumthreads = 0;
|
||
currentthreadid = 0;
|
||
} //end of the function ThreadInitLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownLock( void ) {
|
||
DeleteCriticalSection( &crit );
|
||
threaded = false; //Stupid me... forgot this!!!
|
||
} //end of the function ThreadShutdownLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupSemaphore( void ) {
|
||
semaphore = CreateSemaphore( NULL, 0, 99999999, "bspc" );
|
||
} //end of the function ThreadSetupSemaphore
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownSemaphore( void ) {
|
||
} //end of the function ThreadShutdownSemaphore
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSemaphoreWait( void ) {
|
||
WaitForSingleObject( semaphore, INFINITE );
|
||
} //end of the function ThreadSemaphoreWait
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSemaphoreIncrease( int count ) {
|
||
ReleaseSemaphore( semaphore, count, NULL );
|
||
} //end of the function ThreadSemaphoreIncrease
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )(int) ) {
|
||
int threadid[MAX_THREADS];
|
||
HANDLE threadhandle[MAX_THREADS];
|
||
int i;
|
||
int start, end;
|
||
|
||
Log_Print( "Win32 multi-threading\n" );
|
||
start = I_FloatTime();
|
||
dispatch = 0;
|
||
workcount = workcnt;
|
||
oldf = -1;
|
||
pacifier = showpacifier;
|
||
threaded = true;
|
||
|
||
if ( numthreads == -1 ) {
|
||
ThreadSetDefault();
|
||
}
|
||
|
||
if ( numthreads < 1 || numthreads > MAX_THREADS ) {
|
||
numthreads = 1;
|
||
}
|
||
//
|
||
// run threads in parallel
|
||
//
|
||
InitializeCriticalSection( &crit );
|
||
|
||
numwaitingthreads = 0;
|
||
|
||
if ( numthreads == 1 ) { // use same thread
|
||
func( 0 );
|
||
} //end if
|
||
else
|
||
{
|
||
// printf("starting %d threads\n", numthreads);
|
||
for ( i = 0; i < numthreads; i++ )
|
||
{
|
||
threadhandle[i] = CreateThread(
|
||
NULL, // LPSECURITY_ATTRIBUTES lpsa,
|
||
0, // DWORD cbStack,
|
||
(LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
|
||
(LPVOID)i, // LPVOID lpvThreadParm,
|
||
0, // DWORD fdwCreate,
|
||
&threadid[i] );
|
||
// printf("started thread %d\n", i);
|
||
} //end for
|
||
|
||
for ( i = 0; i < numthreads; i++ )
|
||
WaitForSingleObject( threadhandle[i], INFINITE );
|
||
} //end else
|
||
DeleteCriticalSection( &crit );
|
||
|
||
threaded = false;
|
||
end = I_FloatTime();
|
||
if ( pacifier ) {
|
||
printf( " (%i)\n", end - start );
|
||
}
|
||
} //end of the function RunThreadsOn
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AddThread( void ( *func )(int) ) {
|
||
thread_t *thread;
|
||
|
||
if ( numthreads == 1 ) {
|
||
if ( currentnumthreads >= numthreads ) {
|
||
return;
|
||
}
|
||
currentnumthreads++;
|
||
func( -1 );
|
||
currentnumthreads--;
|
||
} //end if
|
||
else
|
||
{
|
||
ThreadLock();
|
||
if ( currentnumthreads >= numthreads ) {
|
||
ThreadUnlock();
|
||
return;
|
||
} //end if
|
||
//allocate new thread
|
||
thread = GetMemory( sizeof( thread_t ) );
|
||
if ( !thread ) {
|
||
Error( "can't allocate memory for thread\n" );
|
||
}
|
||
|
||
//
|
||
thread->threadid = currentthreadid;
|
||
thread->handle = CreateThread(
|
||
NULL, // LPSECURITY_ATTRIBUTES lpsa,
|
||
0, // DWORD cbStack,
|
||
(LPTHREAD_START_ROUTINE)func, // LPTHREAD_START_ROUTINE lpStartAddr,
|
||
(LPVOID) thread->threadid, // LPVOID lpvThreadParm,
|
||
0, // DWORD fdwCreate,
|
||
&thread->id );
|
||
|
||
//add the thread to the end of the list
|
||
thread->next = NULL;
|
||
if ( lastthread ) {
|
||
lastthread->next = thread;
|
||
} else { firstthread = thread;}
|
||
lastthread = thread;
|
||
//
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "added thread with id %d\n", thread->threadid );
|
||
#endif //THREAD_DEBUG
|
||
//
|
||
currentnumthreads++;
|
||
currentthreadid++;
|
||
//
|
||
ThreadUnlock();
|
||
} //end else
|
||
} //end of the function AddThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RemoveThread( int threadid ) {
|
||
thread_t *thread, *last;
|
||
|
||
//if a single thread
|
||
if ( threadid == -1 ) {
|
||
return;
|
||
}
|
||
//
|
||
ThreadLock();
|
||
last = NULL;
|
||
for ( thread = firstthread; thread; thread = thread->next )
|
||
{
|
||
if ( thread->threadid == threadid ) {
|
||
if ( last ) {
|
||
last->next = thread->next;
|
||
} else { firstthread = thread->next;}
|
||
if ( !thread->next ) {
|
||
lastthread = last;
|
||
}
|
||
//
|
||
FreeMemory( thread );
|
||
currentnumthreads--;
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "removed thread with id %d\n", threadid );
|
||
#endif //THREAD_DEBUG
|
||
break;
|
||
} //end if
|
||
last = thread;
|
||
} //end if
|
||
if ( !thread ) {
|
||
Error( "couldn't find thread with id %d", threadid );
|
||
}
|
||
ThreadUnlock();
|
||
} //end of the function RemoveThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void WaitForAllThreadsFinished( void ) {
|
||
HANDLE handle;
|
||
|
||
ThreadLock();
|
||
while ( firstthread )
|
||
{
|
||
handle = firstthread->handle;
|
||
ThreadUnlock();
|
||
|
||
WaitForSingleObject( handle, INFINITE );
|
||
|
||
ThreadLock();
|
||
} //end while
|
||
ThreadUnlock();
|
||
} //end of the function WaitForAllThreadsFinished
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int GetNumThreads( void ) {
|
||
return currentnumthreads;
|
||
} //end of the function GetNumThreads
|
||
|
||
#endif
|
||
|
||
|
||
//===================================================================
|
||
//
|
||
// OSF1
|
||
//
|
||
//===================================================================
|
||
|
||
#if defined( __osf__ )
|
||
|
||
#define USED
|
||
|
||
#include <pthread.h>
|
||
|
||
typedef struct thread_s
|
||
{
|
||
pthread_t thread;
|
||
int threadid;
|
||
int id;
|
||
struct thread_s *next;
|
||
} thread_t;
|
||
|
||
thread_t *firstthread;
|
||
thread_t *lastthread;
|
||
int currentnumthreads;
|
||
int currentthreadid;
|
||
|
||
int numthreads = 1;
|
||
pthread_mutex_t my_mutex;
|
||
pthread_attr_t attrib;
|
||
static int enter;
|
||
static int numwaitingthreads = 0;
|
||
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetDefault( void ) {
|
||
if ( numthreads == -1 ) { // not set manually
|
||
numthreads = 1;
|
||
} //end if
|
||
qprintf( "%i threads\n", numthreads );
|
||
} //end of the function ThreadSetDefault
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadLock( void ) {
|
||
if ( !threaded ) {
|
||
Error( "ThreadLock: !threaded" );
|
||
return;
|
||
} //end if
|
||
if ( my_mutex ) {
|
||
pthread_mutex_lock( my_mutex );
|
||
} //end if
|
||
if ( enter ) {
|
||
Error( "Recursive ThreadLock\n" );
|
||
}
|
||
enter = 1;
|
||
} //end of the function ThreadLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadUnlock( void ) {
|
||
if ( !threaded ) {
|
||
Error( "ThreadUnlock: !threaded" );
|
||
return;
|
||
} //end if
|
||
if ( !enter ) {
|
||
Error( "ThreadUnlock without lock\n" );
|
||
}
|
||
enter = 0;
|
||
if ( my_mutex ) {
|
||
pthread_mutex_unlock( my_mutex );
|
||
} //end if
|
||
} //end of the function ThreadUnlock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupLock( void ) {
|
||
pthread_mutexattr_t mattrib;
|
||
|
||
Log_Print( "pthread multi-threading\n" );
|
||
|
||
if ( !my_mutex ) {
|
||
my_mutex = GetMemory( sizeof( *my_mutex ) );
|
||
if ( pthread_mutexattr_create( &mattrib ) == -1 ) {
|
||
Error( "pthread_mutex_attr_create failed" );
|
||
}
|
||
if ( pthread_mutexattr_setkind_np( &mattrib, MUTEX_FAST_NP ) == -1 ) {
|
||
Error( "pthread_mutexattr_setkind_np failed" );
|
||
}
|
||
if ( pthread_mutex_init( my_mutex, mattrib ) == -1 ) {
|
||
Error( "pthread_mutex_init failed" );
|
||
}
|
||
}
|
||
|
||
if ( pthread_attr_create( &attrib ) == -1 ) {
|
||
Error( "pthread_attr_create failed" );
|
||
}
|
||
if ( pthread_attr_setstacksize( &attrib, 0x100000 ) == -1 ) {
|
||
Error( "pthread_attr_setstacksize failed" );
|
||
}
|
||
|
||
threaded = true;
|
||
currentnumthreads = 0;
|
||
currentthreadid = 0;
|
||
} //end of the function ThreadInitLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownLock( void ) {
|
||
threaded = false;
|
||
} //end of the function ThreadShutdownLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )(int) ) {
|
||
int i;
|
||
pthread_t work_threads[MAX_THREADS];
|
||
pthread_addr_t status;
|
||
pthread_attr_t attrib;
|
||
pthread_mutexattr_t mattrib;
|
||
int start, end;
|
||
|
||
Log_Print( "pthread multi-threading\n" );
|
||
|
||
start = I_FloatTime();
|
||
dispatch = 0;
|
||
workcount = workcnt;
|
||
oldf = -1;
|
||
pacifier = showpacifier;
|
||
threaded = true;
|
||
|
||
if ( numthreads < 1 || numthreads > MAX_THREADS ) {
|
||
numthreads = 1;
|
||
}
|
||
|
||
if ( pacifier ) {
|
||
setbuf( stdout, NULL );
|
||
}
|
||
|
||
if ( !my_mutex ) {
|
||
my_mutex = GetMemory( sizeof( *my_mutex ) );
|
||
if ( pthread_mutexattr_create( &mattrib ) == -1 ) {
|
||
Error( "pthread_mutex_attr_create failed" );
|
||
}
|
||
if ( pthread_mutexattr_setkind_np( &mattrib, MUTEX_FAST_NP ) == -1 ) {
|
||
Error( "pthread_mutexattr_setkind_np failed" );
|
||
}
|
||
if ( pthread_mutex_init( my_mutex, mattrib ) == -1 ) {
|
||
Error( "pthread_mutex_init failed" );
|
||
}
|
||
}
|
||
|
||
if ( pthread_attr_create( &attrib ) == -1 ) {
|
||
Error( "pthread_attr_create failed" );
|
||
}
|
||
if ( pthread_attr_setstacksize( &attrib, 0x100000 ) == -1 ) {
|
||
Error( "pthread_attr_setstacksize failed" );
|
||
}
|
||
|
||
for ( i = 0 ; i < numthreads ; i++ )
|
||
{
|
||
if ( pthread_create( &work_threads[i], attrib
|
||
, (pthread_startroutine_t)func, (pthread_addr_t)i ) == -1 ) {
|
||
Error( "pthread_create failed" );
|
||
}
|
||
}
|
||
|
||
for ( i = 0 ; i < numthreads ; i++ )
|
||
{
|
||
if ( pthread_join( work_threads[i], &status ) == -1 ) {
|
||
Error( "pthread_join failed" );
|
||
}
|
||
}
|
||
|
||
threaded = false;
|
||
|
||
end = I_FloatTime();
|
||
if ( pacifier ) {
|
||
printf( " (%i)\n", end - start );
|
||
}
|
||
} //end of the function RunThreadsOn
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AddThread( void ( *func )(int) ) {
|
||
thread_t *thread;
|
||
|
||
if ( numthreads == 1 ) {
|
||
if ( currentnumthreads >= numthreads ) {
|
||
return;
|
||
}
|
||
currentnumthreads++;
|
||
func( -1 );
|
||
currentnumthreads--;
|
||
} //end if
|
||
else
|
||
{
|
||
ThreadLock();
|
||
if ( currentnumthreads >= numthreads ) {
|
||
ThreadUnlock();
|
||
return;
|
||
} //end if
|
||
//allocate new thread
|
||
thread = GetMemory( sizeof( thread_t ) );
|
||
if ( !thread ) {
|
||
Error( "can't allocate memory for thread\n" );
|
||
}
|
||
//
|
||
thread->threadid = currentthreadid;
|
||
|
||
if ( pthread_create( &thread->thread, attrib, (pthread_startroutine_t)func, (pthread_addr_t)thread->threadid ) == -1 ) {
|
||
Error( "pthread_create failed" );
|
||
}
|
||
|
||
//add the thread to the end of the list
|
||
thread->next = NULL;
|
||
if ( lastthread ) {
|
||
lastthread->next = thread;
|
||
} else { firstthread = thread;}
|
||
lastthread = thread;
|
||
//
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "added thread with id %d\n", thread->threadid );
|
||
#endif //THREAD_DEBUG
|
||
//
|
||
currentnumthreads++;
|
||
currentthreadid++;
|
||
//
|
||
ThreadUnlock();
|
||
} //end else
|
||
} //end of the function AddThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RemoveThread( int threadid ) {
|
||
thread_t *thread, *last;
|
||
|
||
//if a single thread
|
||
if ( threadid == -1 ) {
|
||
return;
|
||
}
|
||
//
|
||
ThreadLock();
|
||
last = NULL;
|
||
for ( thread = firstthread; thread; thread = thread->next )
|
||
{
|
||
if ( thread->threadid == threadid ) {
|
||
if ( last ) {
|
||
last->next = thread->next;
|
||
} else { firstthread = thread->next;}
|
||
if ( !thread->next ) {
|
||
lastthread = last;
|
||
}
|
||
//
|
||
FreeMemory( thread );
|
||
currentnumthreads--;
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "removed thread with id %d\n", threadid );
|
||
#endif //THREAD_DEBUG
|
||
break;
|
||
} //end if
|
||
last = thread;
|
||
} //end if
|
||
if ( !thread ) {
|
||
Error( "couldn't find thread with id %d", threadid );
|
||
}
|
||
ThreadUnlock();
|
||
} //end of the function RemoveThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void WaitForAllThreadsFinished( void ) {
|
||
pthread_t *thread;
|
||
pthread_addr_t status;
|
||
|
||
ThreadLock();
|
||
while ( firstthread )
|
||
{
|
||
thread = &firstthread->thread;
|
||
ThreadUnlock();
|
||
|
||
if ( pthread_join( *thread, &status ) == -1 ) {
|
||
Error( "pthread_join failed" );
|
||
}
|
||
|
||
ThreadLock();
|
||
} //end while
|
||
ThreadUnlock();
|
||
} //end of the function WaitForAllThreadsFinished
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int GetNumThreads( void ) {
|
||
return currentnumthreads;
|
||
} //end of the function GetNumThreads
|
||
|
||
#endif
|
||
|
||
//===================================================================
|
||
//
|
||
// LINUX
|
||
//
|
||
//===================================================================
|
||
|
||
#if defined( LINUX )
|
||
|
||
#define USED
|
||
|
||
#include <pthread.h>
|
||
#include <semaphore.h>
|
||
|
||
typedef struct thread_s
|
||
{
|
||
pthread_t thread;
|
||
int threadid;
|
||
int id;
|
||
struct thread_s *next;
|
||
} thread_t;
|
||
|
||
thread_t *firstthread;
|
||
thread_t *lastthread;
|
||
int currentnumthreads;
|
||
int currentthreadid;
|
||
|
||
int numthreads = 1;
|
||
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||
pthread_attr_t attrib;
|
||
sem_t semaphore;
|
||
static int enter;
|
||
static int numwaitingthreads = 0;
|
||
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetDefault( void ) {
|
||
if ( numthreads == -1 ) { // not set manually
|
||
numthreads = 1;
|
||
} //end if
|
||
qprintf( "%i threads\n", numthreads );
|
||
} //end of the function ThreadSetDefault
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadLock( void ) {
|
||
if ( !threaded ) {
|
||
Error( "ThreadLock: !threaded" );
|
||
return;
|
||
} //end if
|
||
pthread_mutex_lock( &my_mutex );
|
||
if ( enter ) {
|
||
Error( "Recursive ThreadLock\n" );
|
||
}
|
||
enter = 1;
|
||
} //end of the function ThreadLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadUnlock( void ) {
|
||
if ( !threaded ) {
|
||
Error( "ThreadUnlock: !threaded" );
|
||
return;
|
||
} //end if
|
||
if ( !enter ) {
|
||
Error( "ThreadUnlock without lock\n" );
|
||
}
|
||
enter = 0;
|
||
pthread_mutex_unlock( &my_mutex );
|
||
} //end of the function ThreadUnlock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupLock( void ) {
|
||
pthread_mutexattr_t mattrib;
|
||
|
||
Log_Print( "pthread multi-threading\n" );
|
||
|
||
threaded = true;
|
||
currentnumthreads = 0;
|
||
currentthreadid = 0;
|
||
} //end of the function ThreadInitLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownLock( void ) {
|
||
threaded = false;
|
||
} //end of the function ThreadShutdownLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupSemaphore( void ) {
|
||
sem_init( &semaphore, 0, 0 );
|
||
} //end of the function ThreadSetupSemaphore
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownSemaphore( void ) {
|
||
sem_destroy( &semaphore );
|
||
} //end of the function ThreadShutdownSemaphore
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSemaphoreWait( void ) {
|
||
sem_wait( &semaphore );
|
||
} //end of the function ThreadSemaphoreWait
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSemaphoreIncrease( int count ) {
|
||
int i;
|
||
|
||
for ( i = 0; i < count; i++ )
|
||
{
|
||
sem_post( &semaphore );
|
||
} //end for
|
||
} //end of the function ThreadSemaphoreIncrease
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )(int) ) {
|
||
int i;
|
||
pthread_t work_threads[MAX_THREADS];
|
||
void *pthread_return;
|
||
pthread_attr_t attrib;
|
||
pthread_mutexattr_t mattrib;
|
||
int start, end;
|
||
|
||
Log_Print( "pthread multi-threading\n" );
|
||
|
||
start = I_FloatTime();
|
||
dispatch = 0;
|
||
workcount = workcnt;
|
||
oldf = -1;
|
||
pacifier = showpacifier;
|
||
threaded = true;
|
||
|
||
if ( numthreads < 1 || numthreads > MAX_THREADS ) {
|
||
numthreads = 1;
|
||
}
|
||
|
||
if ( pacifier ) {
|
||
setbuf( stdout, NULL );
|
||
}
|
||
|
||
for ( i = 0 ; i < numthreads ; i++ )
|
||
{
|
||
if ( pthread_create( &work_threads[i], NULL, (void *)func, (void *)i ) == -1 ) {
|
||
Error( "pthread_create failed" );
|
||
}
|
||
}
|
||
|
||
for ( i = 0 ; i < numthreads ; i++ )
|
||
{
|
||
if ( pthread_join( work_threads[i], &pthread_return ) == -1 ) {
|
||
Error( "pthread_join failed" );
|
||
}
|
||
}
|
||
|
||
threaded = false;
|
||
|
||
end = I_FloatTime();
|
||
if ( pacifier ) {
|
||
printf( " (%i)\n", end - start );
|
||
}
|
||
} //end of the function RunThreadsOn
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AddThread( void ( *func )(int) ) {
|
||
thread_t *thread;
|
||
|
||
if ( numthreads == 1 ) {
|
||
if ( currentnumthreads >= numthreads ) {
|
||
return;
|
||
}
|
||
currentnumthreads++;
|
||
func( -1 );
|
||
currentnumthreads--;
|
||
} //end if
|
||
else
|
||
{
|
||
ThreadLock();
|
||
if ( currentnumthreads >= numthreads ) {
|
||
ThreadUnlock();
|
||
return;
|
||
} //end if
|
||
//allocate new thread
|
||
thread = GetMemory( sizeof( thread_t ) );
|
||
if ( !thread ) {
|
||
Error( "can't allocate memory for thread\n" );
|
||
}
|
||
//
|
||
thread->threadid = currentthreadid;
|
||
|
||
if ( pthread_create( &thread->thread, NULL, (void *)func, (void *)thread->threadid ) == -1 ) {
|
||
Error( "pthread_create failed" );
|
||
}
|
||
|
||
//add the thread to the end of the list
|
||
thread->next = NULL;
|
||
if ( lastthread ) {
|
||
lastthread->next = thread;
|
||
} else { firstthread = thread;}
|
||
lastthread = thread;
|
||
//
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "added thread with id %d\n", thread->threadid );
|
||
#endif //THREAD_DEBUG
|
||
//
|
||
currentnumthreads++;
|
||
currentthreadid++;
|
||
//
|
||
ThreadUnlock();
|
||
} //end else
|
||
} //end of the function AddThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RemoveThread( int threadid ) {
|
||
thread_t *thread, *last;
|
||
|
||
//if a single thread
|
||
if ( threadid == -1 ) {
|
||
return;
|
||
}
|
||
//
|
||
ThreadLock();
|
||
last = NULL;
|
||
for ( thread = firstthread; thread; thread = thread->next )
|
||
{
|
||
if ( thread->threadid == threadid ) {
|
||
if ( last ) {
|
||
last->next = thread->next;
|
||
} else { firstthread = thread->next;}
|
||
if ( !thread->next ) {
|
||
lastthread = last;
|
||
}
|
||
//
|
||
FreeMemory( thread );
|
||
currentnumthreads--;
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "removed thread with id %d\n", threadid );
|
||
#endif //THREAD_DEBUG
|
||
break;
|
||
} //end if
|
||
last = thread;
|
||
} //end if
|
||
if ( !thread ) {
|
||
Error( "couldn't find thread with id %d", threadid );
|
||
}
|
||
ThreadUnlock();
|
||
} //end of the function RemoveThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void WaitForAllThreadsFinished( void ) {
|
||
pthread_t *thread;
|
||
void *pthread_return;
|
||
|
||
ThreadLock();
|
||
while ( firstthread )
|
||
{
|
||
thread = &firstthread->thread;
|
||
ThreadUnlock();
|
||
|
||
if ( pthread_join( *thread, &pthread_return ) == -1 ) {
|
||
Error( "pthread_join failed" );
|
||
}
|
||
|
||
ThreadLock();
|
||
} //end while
|
||
ThreadUnlock();
|
||
} //end of the function WaitForAllThreadsFinished
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int GetNumThreads( void ) {
|
||
return currentnumthreads;
|
||
} //end of the function GetNumThreads
|
||
|
||
#endif //LINUX
|
||
|
||
|
||
//===================================================================
|
||
//
|
||
// IRIX
|
||
//
|
||
//===================================================================
|
||
|
||
#ifdef _MIPS_ISA
|
||
|
||
#define USED
|
||
|
||
#include <task.h>
|
||
#include <abi_mutex.h>
|
||
#include <sys/types.h>
|
||
#include <sys/prctl.h>
|
||
|
||
typedef struct thread_s
|
||
{
|
||
int threadid;
|
||
int id;
|
||
struct thread_s *next;
|
||
} thread_t;
|
||
|
||
thread_t *firstthread;
|
||
thread_t *lastthread;
|
||
int currentnumthreads;
|
||
int currentthreadid;
|
||
|
||
int numthreads = 1;
|
||
static int enter;
|
||
static int numwaitingthreads = 0;
|
||
|
||
abilock_t lck;
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetDefault( void ) {
|
||
if ( numthreads == -1 ) {
|
||
numthreads = prctl( PR_MAXPPROCS );
|
||
}
|
||
printf( "%i threads\n", numthreads );
|
||
//@@
|
||
usconfig( CONF_INITUSERS, numthreads );
|
||
} //end of the function ThreadSetDefault
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadLock( void ) {
|
||
spin_lock( &lck );
|
||
} //end of the function ThreadLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadUnlock( void ) {
|
||
release_lock( &lck );
|
||
} //end of the function ThreadUnlock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupLock( void ) {
|
||
init_lock( &lck );
|
||
|
||
Log_Print( "IRIX multi-threading\n" );
|
||
|
||
threaded = true;
|
||
currentnumthreads = 0;
|
||
currentthreadid = 0;
|
||
} //end of the function ThreadInitLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownLock( void ) {
|
||
threaded = false;
|
||
} //end of the function ThreadShutdownLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )(int) ) {
|
||
int i;
|
||
int pid[MAX_THREADS];
|
||
int start, end;
|
||
|
||
start = I_FloatTime();
|
||
dispatch = 0;
|
||
workcount = workcnt;
|
||
oldf = -1;
|
||
pacifier = showpacifier;
|
||
threaded = true;
|
||
|
||
if ( numthreads < 1 || numthreads > MAX_THREADS ) {
|
||
numthreads = 1;
|
||
}
|
||
|
||
if ( pacifier ) {
|
||
setbuf( stdout, NULL );
|
||
}
|
||
|
||
init_lock( &lck );
|
||
|
||
for ( i = 0 ; i < numthreads - 1 ; i++ )
|
||
{
|
||
pid[i] = sprocsp( ( void( * ) ( void *, size_t ) )func, PR_SALL, (void *)i
|
||
, NULL, 0x100000 );
|
||
// pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
|
||
// , NULL, 0x80000);
|
||
if ( pid[i] == -1 ) {
|
||
perror( "sproc" );
|
||
Error( "sproc failed" );
|
||
}
|
||
}
|
||
|
||
func( i );
|
||
|
||
for ( i = 0 ; i < numthreads - 1 ; i++ )
|
||
wait( NULL );
|
||
|
||
threaded = false;
|
||
|
||
end = I_FloatTime();
|
||
if ( pacifier ) {
|
||
printf( " (%i)\n", end - start );
|
||
}
|
||
} //end of the function RunThreadsOn
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AddThread( void ( *func )(int) ) {
|
||
thread_t *thread;
|
||
|
||
if ( numthreads == 1 ) {
|
||
if ( currentnumthreads >= numthreads ) {
|
||
return;
|
||
}
|
||
currentnumthreads++;
|
||
func( -1 );
|
||
currentnumthreads--;
|
||
} //end if
|
||
else
|
||
{
|
||
ThreadLock();
|
||
if ( currentnumthreads >= numthreads ) {
|
||
ThreadUnlock();
|
||
return;
|
||
} //end if
|
||
//allocate new thread
|
||
thread = GetMemory( sizeof( thread_t ) );
|
||
if ( !thread ) {
|
||
Error( "can't allocate memory for thread\n" );
|
||
}
|
||
//
|
||
thread->threadid = currentthreadid;
|
||
|
||
thread->id = sprocsp( ( void( * ) ( void *, size_t ) )func, PR_SALL, (void *)thread->threadid, NULL, 0x100000 );
|
||
if ( thread->id == -1 ) {
|
||
perror( "sproc" );
|
||
Error( "sproc failed" );
|
||
}
|
||
|
||
//add the thread to the end of the list
|
||
thread->next = NULL;
|
||
if ( lastthread ) {
|
||
lastthread->next = thread;
|
||
} else { firstthread = thread;}
|
||
lastthread = thread;
|
||
//
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "added thread with id %d\n", thread->threadid );
|
||
#endif //THREAD_DEBUG
|
||
//
|
||
currentnumthreads++;
|
||
currentthreadid++;
|
||
//
|
||
ThreadUnlock();
|
||
} //end else
|
||
} //end of the function AddThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RemoveThread( int threadid ) {
|
||
thread_t *thread, *last;
|
||
|
||
//if a single thread
|
||
if ( threadid == -1 ) {
|
||
return;
|
||
}
|
||
//
|
||
ThreadLock();
|
||
last = NULL;
|
||
for ( thread = firstthread; thread; thread = thread->next )
|
||
{
|
||
if ( thread->threadid == threadid ) {
|
||
if ( last ) {
|
||
last->next = thread->next;
|
||
} else { firstthread = thread->next;}
|
||
if ( !thread->next ) {
|
||
lastthread = last;
|
||
}
|
||
//
|
||
FreeMemory( thread );
|
||
currentnumthreads--;
|
||
#ifdef THREAD_DEBUG
|
||
qprintf( "removed thread with id %d\n", threadid );
|
||
#endif //THREAD_DEBUG
|
||
break;
|
||
} //end if
|
||
last = thread;
|
||
} //end if
|
||
if ( !thread ) {
|
||
Error( "couldn't find thread with id %d", threadid );
|
||
}
|
||
ThreadUnlock();
|
||
} //end of the function RemoveThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void WaitForAllThreadsFinished( void ) {
|
||
ThreadLock();
|
||
while ( firstthread )
|
||
{
|
||
ThreadUnlock();
|
||
|
||
//wait (NULL);
|
||
|
||
ThreadLock();
|
||
} //end while
|
||
ThreadUnlock();
|
||
} //end of the function WaitForAllThreadsFinished
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int GetNumThreads( void ) {
|
||
return currentnumthreads;
|
||
} //end of the function GetNumThreads
|
||
|
||
#endif //_MIPS_ISA
|
||
|
||
|
||
//=======================================================================
|
||
//
|
||
// SINGLE THREAD
|
||
//
|
||
//=======================================================================
|
||
|
||
#ifndef USED
|
||
|
||
int numthreads = 1;
|
||
int currentnumthreads = 0;
|
||
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetDefault( void ) {
|
||
numthreads = 1;
|
||
} //end of the function ThreadSetDefault
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadLock( void ) {
|
||
} //end of the function ThreadLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadUnlock( void ) {
|
||
} //end of the function ThreadUnlock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupLock( void ) {
|
||
Log_Print( "no multi-threading\n" );
|
||
} //end of the function ThreadInitLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownLock( void ) {
|
||
} //end of the function ThreadShutdownLock
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSetupSemaphore( void ) {
|
||
} //end of the function ThreadSetupSemaphore
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadShutdownSemaphore( void ) {
|
||
} //end of the function ThreadShutdownSemaphore
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSemaphoreWait( void ) {
|
||
} //end of the function ThreadSemaphoreWait
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void ThreadSemaphoreIncrease( int count ) {
|
||
} //end of the function ThreadSemaphoreIncrease
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )(int) ) {
|
||
int start, end;
|
||
|
||
Log_Print( "no multi-threading\n" );
|
||
dispatch = 0;
|
||
workcount = workcnt;
|
||
oldf = -1;
|
||
pacifier = showpacifier;
|
||
start = I_FloatTime();
|
||
#ifdef NeXT
|
||
if ( pacifier ) {
|
||
setbuf( stdout, NULL );
|
||
}
|
||
#endif
|
||
func( 0 );
|
||
|
||
end = I_FloatTime();
|
||
if ( pacifier ) {
|
||
printf( " (%i)\n", end - start );
|
||
}
|
||
} //end of the function RunThreadsOn
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void AddThread( void ( *func )(int) ) {
|
||
if ( currentnumthreads >= numthreads ) {
|
||
return;
|
||
}
|
||
currentnumthreads++;
|
||
func( -1 );
|
||
currentnumthreads--;
|
||
} //end of the function AddThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void RemoveThread( int threadid ) {
|
||
} //end of the function RemoveThread
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
void WaitForAllThreadsFinished( void ) {
|
||
} //end of the function WaitForAllThreadsFinished
|
||
//===========================================================================
|
||
//
|
||
// Parameter: -
|
||
// Returns: -
|
||
// Changes Globals: -
|
||
//===========================================================================
|
||
int GetNumThreads( void ) {
|
||
return currentnumthreads;
|
||
} //end of the function GetNumThreads
|
||
|
||
#endif //USED
|