worker/worker.cpp
2021-02-27 17:44:33 +02:00

272 lines
4.3 KiB
C++

#include "worker.h"
/* WaitObject */
WaitObject::WaitObject()
: m_Type(WaitObject::NoWait)
{
m_lInterval = 0;
m_Func = NULL;
m_pData = NULL;
}
WaitObject::WaitObject(long lInterval)
: m_Type(WaitObject::WaitInterval)
{
m_lInterval = lInterval > 0 ? lInterval : 0;
m_Func = NULL;
m_pData = NULL;
}
WaitObject::WaitObject(WaitFunc func, void* data, long delay)
: m_Type(WaitObject::WaitFunction)
{
m_lInterval = delay > 0 ? delay : 0;
m_Func = func;
m_pData = data;
}
const WaitObject NoWait = WaitObject();
const WaitObject DefWait = WaitObject(100);
/* Worker */
Worker::Worker()
{
m_pData = NULL;
m_bThink = false;
m_iStage = 0;
m_State = workstate::INIT;
m_bRunning = false;
}
Worker::~Worker()
{
}
void Worker::SetName(const std::wstring& name)
{
m_Name = name;
}
std::wstring Worker::GetName() const
{
return m_Name;
}
void Worker::SetData(void* data)
{
m_pData = data;
}
void* Worker::GetData() const
{
return m_pData;
}
void Worker::SetControlFunction(WorkerFunc func)
{
m_Control = func;
}
void Worker::SetWorkerFunction(WorkerFunc func)
{
m_Work = func;
}
void Worker::SetUpdateFunction(WorkerFunc func)
{
m_Update = func;
}
void Worker::SetState(workstate state, bool bRunning)
{
if (m_State == workstate::WAIT && state != m_State)
m_Wait = NoWait;
m_State = state;
m_bRunning = bRunning;
}
workstate Worker::GetState() const
{
return m_State;
}
bool Worker::IsRunning() const
{
return m_bRunning;
}
std::string& Worker::GetExitMessage()
{
return m_Msg;
}
WaitObject& Worker::GetWait()
{
return m_Wait;
}
void Worker::SetStage(int stage)
{
m_iStage = stage;
}
int Worker::GetStage() const
{
return m_iStage;
}
int Worker::GetProgress() const
{
return -1;
}
void Worker::EnableThink(bool bThink)
{
m_bThink = bThink;
}
void Worker::Start()
{
SetState(workstate::INIT, true);
Update();
}
void Worker::Fail(const std::string& msg)
{
SetState(workstate::FAIL, false);
m_Msg = msg;
}
void Worker::Wait(const WaitObject& obj)
{
SetState(workstate::WAIT, true);
m_Wait = obj;
}
void Worker::Continue(int nextStage)
{
SetState(workstate::RUNNING, true);
if (nextStage != -1)
SetStage(nextStage);
}
void Worker::Finish()
{
SetState(workstate::FINISH, false);
}
void Worker::OnException(const std::exception& exc)
{
fprintf(stderr, "%s\n", exc.what());
Fail(exc.what());
}
void Worker::DoControl()
{
if (m_Control)
m_Control(this);
}
void Worker::DoWork()
{
if (m_Work)
m_Work(this);
}
void Worker::Update()
{
try {
if (m_Update)
m_Update(this);
DoControl();
if (m_bThink)
Think();
if (IsRunning() && GetState() != workstate::WAIT)
DoWork();
} catch (const std::exception& exc) {
OnException(exc);
}
}
void Worker::Think()
{
switch(GetState())
{
case workstate::WAIT: DoWait(); break;
default: return;
}
}
void Worker::DoWait()
{
WaitObject& obj = GetWait();
switch(obj.m_Type)
{
case WaitObject::NoWait:
SetState(workstate::RUNNING, true);
break;
case WaitObject::WaitInterval:
Sleep(obj.m_lInterval);
SetState(workstate::RUNNING, true);
break;
case WaitObject::WaitFunction:
if (obj.m_Func(obj.m_pData))
SetState(workstate::RUNNING, true);
else Sleep(obj.m_lInterval);
break;
}
}
void Worker::Run()
{
do {
Update();
} while (IsRunning());
}
/* ThreadWorker */
ThreadWorker::ThreadWorker()
{
m_hThread = INVALID_HANDLE_VALUE;
m_ulThreadId = 0;
}
ThreadWorker::~ThreadWorker()
{
}
unsigned long ThreadWorker::GetThreadId() const
{
return m_ulThreadId;
}
DWORD WINAPI ThreadWorker::_ThreadWorker(LPVOID lpArg)
{
ThreadWorker* wrk = (ThreadWorker*)lpArg;
wrk->SetState(workstate::INIT, false);
wrk->EnableThink(true);
wrk->Update();
wrk->Run();
return !(wrk->GetState() == workstate::FINISH);
}
void ThreadWorker::Start()
{
DWORD dwTid;
m_hThread = CreateThread(NULL, 0, _ThreadWorker, this, 0, &dwTid);
m_ulThreadId = dwTid;
}
void ThreadWorker::JoinThread()
{
WaitForSingleObject(m_hThread, INFINITE);
}