/*
* Thread.h
* Copyright (c) 2011 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*/
// SOL++2000
// 1999.09.24 Modified to use _beginthreadex and _endthreadex insteade
// of CreateThread and ExitThread.
// SOL9
// 2008/09/05
#pragma once
#include <sol\Object.h>
#include <process.h>
#include <sol\stdio.h>
#include <sol\InvalidHandleException.h>
namespace SOL {
typedef unsigned (__stdcall *LPTHREAD_PROC)(void*);
class Thread :public Object {
public:
static const UINT WM_SOL_THREAD_CANCEL = (WM_USER+2009);
private:
void* param;
DWORD threadId;
HANDLE handle;
static DWORD WINAPI procedure(DWORD dword) {
Thread* thread = (Thread*)dword;
if(thread) {
// SOL++2000
thread -> run();
}
return True;
}
protected:
void setHandle(HANDLE handle1) {
handle = handle1;
}
void setThreadId(int id) {
threadId = id;
}
public:
Thread(DWORD stack = 0, void* param = NULL){
this -> param = param;
// Create a suspended thread.
DWORD flags = CREATE_SUSPENDED;
handle = (HANDLE)_beginthreadex((void*)NULL, (unsigned)stack,
(LPTHREAD_PROC)Thread::procedure,
(void*)this, flags, (unsigned*)&threadId);
if(handle == NULL || handle == INVALID_HANDLE_VALUE) {
handle = NULL;
throw InvalidHandleException("Failed to create a thread",
GetLastError());
}
}
~Thread() {
kill();
}
void* getParam() {
return param;
}
DWORD getThreadId() {
return threadId;
}
HANDLE getHandle() {
return handle;
}
void exit(DWORD exitCode) {
//::ExitThread(exitCode);
_endthreadex(exitCode);
}
// Thread main loop
virtual void run() {
// Do something
//return TRUE;
}
// SOL++ 3.0
virtual DWORD start() {
return resume();
}
void sleep(DWORD time) {
::Sleep(time);
}
DWORD resume() {
return ::ResumeThread(handle);
}
void setPriority(int priority) {
::SetThreadPriority(handle, priority);
}
DWORD suspend() {
//Please be carefull to use this method,
//because this may cause a something deadlock.
return ::SuspendThread(handle);
}
BOOL close() {
if(handle) {
HANDLE h = handle;
handle = NULL;
return ::CloseHandle(h);
}
return FALSE;
}
BOOL post(UINT message, WPARAM wParam, LPARAM lParam) {
if(handle) {
return ::PostThreadMessage(threadId, message, wParam, lParam);
}
else {
return FALSE;
}
}
BOOL getExitCode(DWORD* id) {
return ::GetExitCodeThread(handle, id);
}
void kill() {
if(handle) {
close();
DWORD id;
while(getExitCode(&id)) {
if(id == STILL_ACTIVE) {
dispatchMessage();
continue;
}
else {
break;
}
}
}
handle = NULL;
}
BOOL terminate(int exitCode) {
return ::TerminateThread(handle, exitCode);
}
int wait(int interval=INFINITE) {
return ::WaitForSingleObject(handle, interval);
}
/*
public:
//2009/11/16
void msgWait(){
while (true)
if (MsgWaitForMultipleObjects(1, &handle, FALSE,
INFINITE, QS_ALLINPUT|QS_ALLEVENTS) == WAIT_OBJECT_0+1 ) {
dispatchMessage();
}else {
break;
}
}
*/
//2009/11/16
private:
void dispatchMessage()
{
MSG msg;
while(PeekMessage (&msg,NULL,0,0,PM_REMOVE)) {
SleepEx(10, TRUE);
if (msg.message == WM_SOL_THREAD_CANCEL) {
terminate(0);
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
public:
virtual void stop() {
post(WM_SOL_THREAD_CANCEL, 0, 0);
}
public:
UINT getCancelMessage() {
return WM_SOL_THREAD_CANCEL;
}
};
}
|