Source code
/*
* Thread.h
* Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
*/
#pragma once
#include <viz++\Object.h>
#include <process.h>
#include <viz++\InvalidHandleException.h>
namespace VIZ {
typedef unsigned (__stdcall *LPTHREAD_PROC)(void*);
class Thread :public Object {
public:
static const UINT WM_VIZ_THREAD_CANCEL = (WM_USER+2009);
private:
void* param;
DWORD threadId;
HANDLE handle;
static DWORD WINAPI procedure(void* ptr) {
Thread* thread = (Thread*)ptr;
if(thread) {
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;
}
// VIZ++ 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) {
BOOL rc = FALSE;
if (handle) {
rc = TerminateThread(handle, exitCode);
}
return rc;
}
int wait(int interval=INFINITE) {
int rc = 0;
if (handle) {
rc = ::WaitForSingleObject(handle, interval);
}
return rc;
}
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_VIZ_THREAD_CANCEL) {
terminate(0);
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
public:
virtual void stop() {
post(WM_VIZ_THREAD_CANCEL, 0, 0);
}
public:
UINT getCancelMessage() {
return WM_VIZ_THREAD_CANCEL;
}
};
}
Last modified: 10 Feb 2017
Copyright (c) 2009-2017 Antillia.com ALL RIGHTS RESERVED.