////////////////////////////////////////////////////////////
//
// Implementation of classes
// AThreadAttributes, AThread, AAsyncStep, AThreadControl
//
// Copyright 2001
//
////////////////////////////////////////////////////////////
#include "AThread.h"
#include "AWait.h"
#include "ASchedule.h"
// AThreadAttributes
AThreadAttributes::AThreadAttributes()
{
status = ::pthread_attr_init(&attributes);
// as default in HP
int z=64*1024; // if(z<PTHREAD_STACK_MIN) z=PTHREAD_STACK_MIN;
if(!status) status=::pthread_attr_setstacksize(&attributes,(size_t)z);
if(!status) status=::pthread_attr_setinheritsched(&attributes,PTHREAD_INHERIT_SCHED);
if(!status) status=::pthread_attr_setscope(&attributes,PTHREAD_SCOPE_SYSTEM);
}
AThreadAttributes::~AThreadAttributes()
{
if( !status )
::pthread_attr_destroy(&attributes);
}
int AThreadAttributes::set_priority(int z)
{
if( status ) return -1;
AScheduleAttributes schedule_attributes;
schedule_attributes.set_priority(z);
sched_param parameters;
schedule_attributes.get(parameters);
if( ::pthread_attr_setinheritsched(&attributes,PTHREAD_EXPLICIT_SCHED) ) return -2;
return ::pthread_attr_setschedparam(&attributes,¶meters);
}
int AThreadAttributes::set_guard_size(int z)
{
if( status ) return -1;
if(z<0) return -2;
return ::pthread_attr_setguardsize(&attributes,(size_t)z);
}
int AThreadAttributes::set_stack_size(int z)
{
if( status ) return -1;
// if(z<PTHREAD_STACK_MIN) return -2;
return ::pthread_attr_setstacksize(&attributes,(size_t)z);
}
int AThreadAttributes::set_detached()
{
if( status ) return -1;
return ::pthread_attr_setdetachstate(&attributes,PTHREAD_CREATE_DETACHED);
}
int AThreadAttributes::set_schedule_policy(int z)
{
if( status ) return -1;
// see sched.h, rtsched(2)
// need to set explicit schedule before setschedpolicy()
if( ::pthread_attr_setinheritsched(&attributes,PTHREAD_EXPLICIT_SCHED) ) return -2;
return ::pthread_attr_setschedpolicy(&attributes,z);
}
int AThreadAttributes::set_process_scope()
{
if( status ) return -1;
return ::pthread_attr_setscope(&attributes,PTHREAD_SCOPE_PROCESS);
}
// AThread
void AThread::selfdestruct()
{
// this order !
destruct=true;
loop_sleep=0;
wake_up();
}
int AThread::startup()
{
int dummy;
::pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,&dummy);
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&dummy);
return 0;
}
// AAsyncStep
int AAsyncStep::loop(bool& continue_loop)
{
continue_loop=true;
int g=respond();
if(g) return g;
AWait(thread_condition,thread_mutex);
return 0;
}
// AThreadControl
// creates the thread, which begins executing using the AThread object
int AThreadControl::launch( AThread& cAThread, AThreadAttributes& a )
{
int g=0;
thread_object=&cAThread;
if(! thread_object || a.status)
return 1;
g = pthread_create( &handle, &a.attributes, thread_procedure, thread_object);
if(g) return 2;
return 0;
}
// creates the thread, which begins executing using the AThread object
int AThreadControl::launch( AThread& cAThread)
{
thread_object=&cAThread;
if(! thread_object )
return -1;
return pthread_create( &handle, 0, thread_procedure, thread_object);
}
int AThreadControl::get_priority(int& priority)
{
if(! thread_object) return -1;
int g=0;
int policy;
sched_param parameters;
g=pthread_getschedparam(handle,&policy,¶meters);
if(g) priority=parameters.sched_priority;
return g;
}
int AThreadControl::change_priority(int priority)
{
if(! thread_object) return -1;
int g=0;
int policy;
sched_param parameters;
g=pthread_getschedparam(handle,&policy,¶meters);
if(!g)
{
parameters.sched_priority=priority;
g=pthread_setschedparam(handle,policy,¶meters);
}
return g;
}
int AThreadControl::detach()
{
if(! thread_object) return -1;
return pthread_detach(handle);
}
// suspend the thread
int AThreadControl::suspend()
{
if(! thread_object) return -1;
return ::pthread_suspend(handle);
}
// continue the thread
int AThreadControl::resume()
{
if(! thread_object) return -1;
return ::pthread_continue( handle);
}
// cancel the thread
int AThreadControl::terminate()
{
if(! thread_object) return -1;
return ::pthread_cancel( handle);
}
void* AThreadControl::thread_procedure(void *pAThread)
{
int hr1=0,hr2=0,hr3=0,hr4=0;
bool loop=true;
//AThread *p_thread = static_cast<AThread *>(pAThread);
AThread *p_thread = (AThread *)(pAThread);
if(p_thread->destruct)
{
return (void*)destructed;
}
p_thread->thread_mutex.lock();
hr1=p_thread->startup();
if(! hr1)
while(loop)
{
pthread_testcancel();
if(p_thread->destruct)
{
hr2=1;
break;
}
hr3=p_thread->loop(loop);
if(hr3) break;
if(p_thread->destruct)
{
hr2=1;
break;
}
if(p_thread->loop_sleep>0)
AWait(p_thread->thread_condition,p_thread->thread_mutex,p_thread->loop_sleep);
//sleep(p_thread->loop_sleep);
}
hr4=p_thread->cleanup();
p_thread->thread_mutex.unlock();
unsigned hr=0;
if(hr1) hr=failed_startup;
else if(hr2) hr=destructed;
else if(hr3) hr=bad_loop;
else if(hr4) hr=failed_cleanup;
return (void*)hr;
}