// Thread.cpp V0.1pre Provides thread class member functions
// © 2003 Elliot
Nierman
#include "thread.h"
Thread::Thread()
{
#ifdef WIN
T_Var.w_handle = 0;
T_Var.w_id = 0;
T_Var.b_susp = true;
T_Var.b_term = false;
T_Var.b_created = false;
T_Var.b_state = CREATED;
#endif
#ifdef POSIX
T_Var.p_handle = 0;
T_Var.b_susp = true;
T_Var.b_term = false;
T_Var.b_created = false;
pthread_attr_init(&T_Var.p_attr);
pthread_mutex_init(&T_Var.p_mux,
NULL);
pthread_cond_init(&T_Var.p_cond,
NULL);
#endif
}
// CreateSuspended()
// Description: Creates a thread in a suspended state
bool Thread::CreateSuspended()
{
#ifdef WIN
T_Var.w_handle = reinterpret_cast<HANDLE>(_beginthreadex(
0, 0,
w_threadfunc,
this, CREATE_SUSPENDED, &T_Var.w_id));
#endif
#ifdef POSIX
pthread_attr_init(&T_Var.p_attr);
Start_Suspended();
#endif
return true;
}
// CreateSuspended()
// Description: Creates a thread in a suspended state with an
// associated stack size given by stack_size
bool Thread::CreateSuspended(unsigned long stack_size)
{
#ifdef WIN
T_Var.w_handle = reinterpret_cast<HANDLE>(_beginthreadex(
0, stack_size,
w_threadfunc,
this, CREATE_SUSPENDED, &T_Var.w_id));
#endif
#ifdef POSIX
pthread_attr_init(&T_Var.p_attr);
pthread_attr_setstacksize(&T_Var.p_attr,
stack_size);
Start_Suspended();
#endif
return true;
}
// Create()
// Description: Creates a thread in a running state
bool Thread::Create()
{
#ifdef WIN
T_Var.b_susp = false;
T_Var.w_handle = reinterpret_cast<HANDLE>(_beginthreadex(
0, 0,
w_threadfunc,
this, 0 , &T_Var.w_id));
#endif
#ifdef POSIX
pthread_attr_init(&T_Var.p_attr);
Start();
#endif
return true;
}
// Create(unsigned long stack_size)
// Description: Creates a thread in a running state with a associated
// stack sizeas specified by stack_size
bool Thread::Create(unsigned long stack_size)
{
#ifdef WIN
T_Var.b_susp = false;
T_Var.w_handle = reinterpret_cast<HANDLE>(_beginthreadex(
0, stack_size,
w_threadfunc,
this, 0 , &T_Var.w_id));
if (T_Var.w_handle)
return
true;
#endif
#ifdef POSIX
pthread_attr_init(&T_Var.p_attr);
pthread_attr_setstacksize(&T_Var.p_attr,
stack_size);
Start();
#endif
return true;
}
// Execute()
// Description : Called to begin execution of the EntryRoutine()
// of a thread which has been constructed.
bool Thread::Execute()
{
Resume();
}
// GetID()
// Description: Cross-Platform function which returns the thread ID
// provided by the operating system at thread creation time.
unsigned int Thread::GetID() const
{
#ifdef WIN
return T_Var.w_id;
#endif
#ifdef POSIX
while(T_Var.b_created == true
&& T_Var.p_handle == 0)
usleep();
return T_Var.p_handle;
#endif
}
// GetPriority()
// Description: Returns a character pointer corresponding to the
// priority_level of the given thread.
char * Thread::GetPriority()
{
#ifdef POSIX
//This depends on the implemented priority levels
//and must currently be entered by the user
#endif
#ifdef WIN
switch (T_Var.b_prio)
{
case
THREAD_PRIORITY_IDLE : return "IDLE";
break;
case
THREAD_PRIORITY_LOWEST : return "LOWEST";
break;
case
THREAD_PRIORITY_BELOW_NORMAL : return "BELOW_NORMAL";
break;
case
THREAD_PRIORITY_NORMAL : return "NORMAL";
break;
case
THREAD_PRIORITY_ABOVE_NORMAL : return "ABOVE_NORMAL";
break;
case
THREAD_PRIORITY_HIGHEST : return "HIGHEST";
break;
case
THREAD_PRIORITY_TIME_CRITICAL : return "TIME_CRITICAL";
break;
}
#endif
return NULL;
}
// Join()
// Description: Causes the calling thread to be blocked until
// execution of the thread referenced by the call completes.
bool Thread::Join() const
{
#ifdef WIN
if (WaitForSingleObject(T_Var.w_handle,
INFINITE) == WAIT_OBJECT_0)
return
true;
return false;
#endif
#ifdef POSIX
pthread_join(GetID(), NULL);
return true;
#endif
}
// Resume()
// Description: Resumes execution of a thread
// which has been suspended by a call to Suspend()
void Thread::Resume()
{
#ifdef WIN
if (T_Var.b_susp)
{
T_Var.b_susp = false;
ResumeThread(T_Var.w_handle);
}
#endif
#ifdef POSIX
if (!T_Var.b_created)
Start();
else
T_Var.b_susp
= false;
pthread_mutex_lock(&T_Var.p_mux);
if (T_Var.b_susp == false) pthread_cond_broadcast(&T_Var.p_cond);
pthread_mutex_unlock(&T_Var.p_mux);
#endif
}
// SafePoint()
// Description: Called by user in the user-overridden function EntryRoutine()
// to indicate a region of code where it is safe to test for and implement
// thread preemption.
void Thread::SafePoint()
{
#ifdef POSIX
if (T_Var.b_susp)
Suspend_Thread();
if (T_Var.b_term)
pthread_cancel(T_Var.p_handle);
#endif
#ifdef WIN
if (T_Var.b_susp)
SuspendThread(T_Var.w_handle);
if (T_Var.b_term)
_endthreadex(0);
#endif
}
// SetPriority()
// Description: Sets the priority level of a given thread to the level
// specified with the variable priority level. The enumerated type
// priority_level is defined in thread.h
bool Thread::SetPriority( priority_level priority )
{
#ifdef WIN
T_Var.b_prio = priority;
if( SetThreadPriority (T_Var.w_handle,
priority) )
return
true;
else
return
false;
#endif
#ifdef POSIX
// To be posted by 10/29/02
#endif
}
//T_Sleep(unsigned long millisecs)
// Description: Member function adds transparent sleep functionality
// across POSIX/Win32 systems.
void Thread::T_Sleep(unsigned long millisecs)
{
#ifdef WIN
Sleep(millisecs);
#endif
#ifdef POSIX
usleep(millisecs*1000)
#endif
}
//Terminate()
// Description: Sets a flag to indicate a request for thread termination
// which will be processed on the next call to SafePoint().
void Thread::Terminate()
{
T_Var.b_term = true;
}
// Suspend()
// Description: Sets a flag to indicate a request for suspension of
// thread execution which is processed on the next call to SafePoint().
void Thread::Suspend()
{
T_Var.b_susp = true;
}
void Thread::Suspend_Thread()
{
#ifdef POSIX
pthread_mutex_lock(&T_Var.p_mux);
while (T_Var.b_susp == true)
pthread_cond_wait(&T_Var.p_cond,
&T_Var.p_mux);
pthread_mutex_unlock(&T_Var.p_mux);
#endif
}
// w_threadfunc(void *args)
// Description: Private Win32 function which provides the
// object-oriented encapsulation of the thread
#ifdef WIN
unsigned int __stdcall Thread::w_threadfunc(void *args)
{
Thread *pThread = reinterpret_cast<Thread*>(args);
if (pThread)
pThread->ThreadRoutine();
_endthreadex( 0 );
return 0;
}
#endif
// threadfunc(Thread * NewThread)
// Description: Private POSIX Thread threadfunc associated with a
// thread which is created in a running state by Create() on a
// POSIX platform
#ifdef POSIX
void Thread::threadfunc(Thread * NewThread)
{
NewThread->T_Var.b_susp =
false;
NewThread->ThreadRoutine();
NewThread->T_Var.b_term =
true;
}
#endif
// susp_threadfunc(Thread * NewThread)
// Description: Private POSIX Thread function encapsulating a
// thread which is created in a b_susp state by Construct().
#ifdef POSIX
void Thread::susp_threadfunc(Thread * NewThread)
{
NewThread->T_Var.b_susp =
true;
NewThread->ThreadRoutine();
NewThread->T_Var.b_term =
true;
}
#endif
// Start()
// Description: Private POSIX function which instantiates a pthread
// in a running state.
#ifdef POSIX
void Thread::Start(void)
{
T_Var.b_created = true;
if (pthread_create(&T_Var.p_handle,
&T_Var.p_attr, (void *(*)(void*))&threadfunc, this))
//Thread
creation unsucessful
T_Var.p_handle
= 0;
}
#ifdef FIFO
pthread_attr_setschedpolicy(&T_Var.p_attr,
SCHED_FIFO);
#endif
#ifdef RR
pthread_attr_setschedpolicy(&T_Var.p_attr,
SCHED_RR);
#endif
pthread_attr_setschedparam(&T_Var.p_attr,
&T_Var.p_param);
T_Var.b_created = true;
}
#endif
//Start_Suspended(void)
// Description: Private POSIX member function which instantiates
// a pthread in a suspended state.
#ifdef POSIX
void Thread::Start_Suspended(void)
{
T_Var.b_created = true;
if (pthread_create(&T_Var.p_handle,
&T_Var.p_attr, (void *(*)(void*))&susp_threadfunc, this))
{
T_Var.b_term
= true;
T_Var.p_handle
= 0;
}
#ifdef FIFO
pthread_attr_setschedpolicy(&p_attr,
SCHED_FIFO);
#endif
#ifdef RR
pthread_attr_setschedpolicy(&p_attr,
SCHED_RR);
#endif
pthread_attr_setschedparam(&T_Var.p_attr,
&T_Var.p_param);
T_Var.b_created = true;
}
#endif