////////////////////////////////////////////////////////////
//
// Declaration of classes
// AThreadAttributes, AThread, AAsyncStep, AThreadControl
//
// Copyright 2001 Alexander Liss
//
////////////////////////////////////////////////////////////
#ifndef __THREAD_H__
#define __THREAD_H__
#include "AMutex.h"
#include "ACondition.h"
// for a thread we need two objects
// one of a type AThread, another of a type AThreadControl
// it is best to allocate them in
// a global space, a heap or a stack of main()
class AThreadControl;
// AThreadAttributes
class AThreadAttributes
{
friend class AThreadControl;
public:
int status;
// for POSIX kernel threads:
// inherit shedule, system scope, stack size 64K, automatically allocates stack
AThreadAttributes();
~AThreadAttributes();
// for POSIX kernel threads: see sched.h, rtsched(2),
// policy indexes are different for kernel threads and old dce threads
int set_schedule_policy(int z);
// for POSIX kernel threads:
// works only with automatically allocated stack address (default)
// zero guard size - no guarding
// default value is PAGESIZE (rounds to a multiple of PAGESIZE)
int set_guard_size(int z);
// for POSIX kernel threads minimal size is PTHREAD_STACK_MIN
int set_stack_size(int z);
int set_priority(int z);
int set_detached();
int set_process_scope();
private:
pthread_attr_t attributes;
};
// in-thread processing
// AThread
// base class;
// derived class supplies procedures and data (!) for a thread;
// if the same derived class is used to create different threads,
// then threads share procedures (!), but do not share data
class AThread
{
friend class AThreadControl;
public:
AThread():loop_sleep(0),destruct(false){}
virtual ~AThread(){}
// wait on thread's mutex-condition pair, to respond to wake_up() and selfdestruct()
// used when there is no internal waits in loop() function
void sleep_in_loop(unsigned milliseconds){loop_sleep=milliseconds;}
// one step of a loop between waits
void wake_up(){thread_condition.signal();}
void selfdestruct();
protected:
// in addition to the constructor, called inside the thread function
// Note - default implementation is non-trivial,
// at override call AThread::startup(); in the beginning
virtual int startup();
virtual int loop(bool& continue_loop)
{continue_loop=false; return 0;}
// cleanup what startup() had allocated or opened
virtual int cleanup(){return 0;}
unsigned loop_sleep;
bool destruct;
AMutex thread_mutex;
ACondition thread_condition;
};
// AAsyncStep
class AAsyncStep:public AThread
{
AAsyncStep(const AAsyncStep&);
AAsyncStep& operator=(const AAsyncStep&);
public:
AAsyncStep(){}
int step(){wake_up();return 0;}
protected:
virtual int respond()=0;
private:
int loop(bool& continue_loop);
};
// thread management
// AThreadControl
class AThreadControl
{
friend int AWait(AThreadControl&);
AThreadControl(const AThreadControl&);
AThreadControl& operator=(const AThreadControl&);
public:
// thread return values
enum
{
destructed=0,
failed_startup=1,
bad_loop=2,
failed_cleanup=3
};
AThreadControl():thread_object(0){}
~AThreadControl(){}
// launch the thread
int launch( AThread& thread, AThreadAttributes& atributes);
// launch the thread with default attributes
int launch( AThread& thread);
// following functions can be called only after launch():
int get_priority(int& priority);
// a calling process
// should have appropriate privileges to call this:
int change_priority(int priority);
int detach();
int suspend(); // suspend the thread
int resume(); // continue the thread
int terminate();// cancel the thread
protected:
AThread * thread_object;
pthread_t handle;
static void* thread_procedure(void *thread);
};
#endif