#include "WorkerThread.h" #include "IGpThreadEvent.h" #include "IGpSystemServices.h" #include "PLCore.h" #include "PLDrivers.h" #include #include namespace PortabilityLayer { class WorkerThreadImpl final : public WorkerThread { public: WorkerThreadImpl(); bool Init(); void Destroy() override; void AsyncExecuteTask(Callback_t callback, void *context) override; private: ~WorkerThreadImpl() override; static int StaticThreadFuncThunk(void *context); int ThreadFunc(); IGpThreadEvent *m_wakeSignal; IGpThreadEvent *m_wakeConsumedSignal; Callback_t m_waitingCallback; void *m_waitingContext; bool m_terminated; bool m_threadRunning; }; } void PortabilityLayer::WorkerThreadImpl::Destroy() { this->~WorkerThreadImpl(); DisposePtr(this); } void PortabilityLayer::WorkerThreadImpl::AsyncExecuteTask(PortabilityLayer::WorkerThread::Callback_t callback, void *context) { m_waitingCallback = callback; m_waitingContext = context; m_wakeSignal->Signal(); m_wakeConsumedSignal->Wait(); } PortabilityLayer::WorkerThreadImpl::WorkerThreadImpl() : m_wakeSignal(nullptr) , m_wakeConsumedSignal(nullptr) , m_waitingCallback(nullptr) , m_waitingContext(nullptr) , m_terminated(false) , m_threadRunning(false) { } PortabilityLayer::WorkerThreadImpl::~WorkerThreadImpl() { if (m_threadRunning) { m_terminated = true; m_wakeSignal->Signal(); m_wakeConsumedSignal->Wait(); } if (m_wakeSignal) m_wakeSignal->Destroy(); if (m_wakeConsumedSignal) m_wakeConsumedSignal->Destroy(); } int PortabilityLayer::WorkerThreadImpl::StaticThreadFuncThunk(void *context) { return static_cast(context)->ThreadFunc(); } int PortabilityLayer::WorkerThreadImpl::ThreadFunc() { m_wakeSignal->Wait(); m_wakeConsumedSignal->Signal(); for (;;) { m_wakeSignal->Wait(); if (m_terminated) { m_wakeConsumedSignal->Signal(); return 0; } else { Callback_t callback = m_waitingCallback; void *context = m_waitingContext; m_wakeConsumedSignal->Signal(); callback(context); } } } bool PortabilityLayer::WorkerThreadImpl::Init() { IGpSystemServices *sysServices = PLDrivers::GetSystemServices(); m_wakeSignal = sysServices->CreateThreadEvent(true, false); if (!m_wakeSignal) return false; m_wakeConsumedSignal = sysServices->CreateThreadEvent(true, false); if (!m_wakeConsumedSignal) return false; if (!sysServices->CreateThread(PortabilityLayer::WorkerThreadImpl::StaticThreadFuncThunk, this)) return false; m_threadRunning = true; m_wakeSignal->Signal(); m_wakeConsumedSignal->Wait(); return true; } PortabilityLayer::WorkerThread::WorkerThread() { } PortabilityLayer::WorkerThread::~WorkerThread() { } PortabilityLayer::WorkerThread *PortabilityLayer::WorkerThread::Create() { void *storage = NewPtr(sizeof(PortabilityLayer::WorkerThreadImpl)); if (!storage) return nullptr; PortabilityLayer::WorkerThreadImpl *thread = new (storage) PortabilityLayer::WorkerThreadImpl(); if (!thread->Init()) { thread->Destroy(); return nullptr; } return thread; }