From aa77548bd637ffd1a7461136e6206906dc4c61c7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 11:54:45 +0100 Subject: New WorkItem/job/promise/future based interface --- lib/worker.cpp | 3 +- lib/worker.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/worker.cpp b/lib/worker.cpp index 4f1352d..7e7f296 100644 --- a/lib/worker.cpp +++ b/lib/worker.cpp @@ -1,5 +1,4 @@ #include "worker.h" -#include "work.h" #include #include #include @@ -19,7 +18,7 @@ Worker::~Worker() } void -Worker::addWork(WorkPtr j) +Worker::addWorkPtr(WorkPtr j) { std::lock_guard lck {todoMutex}; todoLen.release(); diff --git a/lib/worker.h b/lib/worker.h index 96593d9..5356606 100644 --- a/lib/worker.h +++ b/lib/worker.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include #include @@ -9,28 +11,93 @@ #include #include -class Work; class Worker { +public: + class WorkItem { + public: + WorkItem() = default; + virtual ~WorkItem() = default; + NO_MOVE(WorkItem); + NO_COPY(WorkItem); + + virtual void doWork() = 0; + }; + + template class WorkItemT : public WorkItem { + public: + T + get() + { + return future.get(); + } + + protected: + std::promise promise; + std::future future {promise.get_future()}; + friend Worker; + }; + + template + static auto + addWork(Params &&... params) + { + return instance.addWorkImpl(std::forward(params)...); + } + template using WorkPtrT = std::shared_ptr>; + private: + template class WorkItemTImpl : public WorkItemT { + public: + WorkItemTImpl(Params &&... params) : params {std::forward(params)...} { } + + private: + void + doWork() override + { + try { + if constexpr (std::is_void_v) { + std::apply( + [](auto &&... p) { + return std::invoke(p...); + }, + params); + WorkItemT::promise.set_value(); + } + else { + WorkItemT::promise.set_value(std::apply( + [](auto &&... p) { + return std::invoke(p...); + }, + params)); + } + } + catch (...) { + WorkItemT::promise.set_exception(std::current_exception()); + } + } + + std::tuple params; + }; + Worker(); ~Worker(); NO_COPY(Worker); NO_MOVE(Worker); - using WorkPtr = std::unique_ptr; + using WorkPtr = std::shared_ptr; - template - void - addWork(Params &&... params) - requires std::is_base_of_v + template + auto + addWorkImpl(Params &&... params) { - addWork(std::make_unique(std::forward(params)...)); + using T = decltype(std::invoke(std::forward(params)...)); + auto work = std::make_shared>(std::forward(params)...); + addWorkPtr(work); + return work; } - void addWork(WorkPtr w); - -private: + void addWorkPtr(WorkPtr w); void worker(); using Threads = std::vector; -- cgit v1.2.3