// Common, groups WinWrap, Thread
// Copyright Alexander Liss
#ifndef __THREAD_H__
#define __THREAD_H__
#include "kernel.h"
#include "event.h"
// for a thread we need two objects
// one of type Thread, another of type ThreadControl
// it is best to allocate them in
// the global space, the heap or the stack of main()
// Thread
class ThreadControl;
// thread driver
// 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 Thread
{
friend class ThreadControl;
public:
Thread():loop_sleep(0),destruct(false){}
virtual ~Thread(){}
// wait on thread_event
void sleep_in_loop(unsigned milliseconds){loop_sleep=milliseconds;}
void wake_up(){thread_event.set();} // one step of a loop
void selfdestruct();
protected:
// in addition to the constructor
virtual int startup(){return 0;}
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;
Event thread_event;
};
// AsyncStep
class AsyncStep:public Thread
{
public:
AsyncStep(){}
int step(){wake_up();return 0;}
protected:
virtual int respond()=0;
private:
int loop(bool& continue_loop);
};
// ThreadControl
class ThreadControl: public Kernel
{
ThreadControl(const ThreadControl&);
ThreadControl& operator=(const ThreadControl&);
public:
// tread return values
enum
{
destructed=0,
failed_startup=1,
bad_loop=2,
failed_cleanup=3
};
ThreadControl():thread_id(0),thread_object(0){}
~ThreadControl(){}
// launch the thread, use flags if want some features of the thread at its creation
int launch( Thread& cThread,
unsigned uInitFlag = 0, // launch running
LPSECURITY_ATTRIBUTES lpSecurity = NULL,
unsigned uStackSize = 0); // same as caller's
BOOL set_priority( int nPriority);
DWORD suspend();
DWORD resume();
BOOL terminate( DWORD dwExitCode=0);
BOOL get_exit_code( DWORD *pdwExitCode);
int get_priority();
DWORD get_thread_id()const;
// queue an asynchronous procedure call to this thread
//VOID (APIENTRY *PAPCFUNC)( DWORD dwData );
#if(_WIN32_WINNT >= 0x0400)
DWORD queue_APC(PAPCFUNC pfnAPC,DWORD dwData);
#endif
protected:
Thread * thread_object;
unsigned thread_id;
static unsigned _stdcall thread_procedure(void *pThread);
};
#endif