From f8ee56f6dc8cf7e92c4bfc5930d32b14f634141c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 13:13:47 +0100 Subject: Current thread partakes in work effort while waiting This will prevent deadlock if the work pool is otherwise busy by ensuring work is always being done --- lib/worker.cpp | 21 +++++++++++++++++++++ lib/worker.h | 26 ++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/worker.cpp b/lib/worker.cpp index 7e7f296..45fb6df 100644 --- a/lib/worker.cpp +++ b/lib/worker.cpp @@ -42,3 +42,24 @@ Worker::worker() j->doWork(); } } + +void +Worker::assist() +{ + auto job = [this]() { + using namespace std::chrono_literals; + if (todoLen.try_acquire_for(100us)) { + if (std::lock_guard lck {todoMutex}; todo.size()) { + WorkPtr x = std::move(todo.front()); + if (x) { + todo.pop_front(); + } + return x; + } + } + return WorkPtr {}; + }; + if (auto j = job()) { + j->doWork(); + } +} diff --git a/lib/worker.h b/lib/worker.h index 1bc7c14..d9a5a6f 100644 --- a/lib/worker.h +++ b/lib/worker.h @@ -14,12 +14,20 @@ class Worker { public: class WorkItem { - public: - WorkItem() = default; + protected: + WorkItem(Worker * worker) : worker {worker} { } virtual ~WorkItem() = default; NO_MOVE(WorkItem); NO_COPY(WorkItem); + void + assist() const + { + worker->assist(); + } + Worker * worker; + + public: virtual void doWork() = 0; }; @@ -28,10 +36,16 @@ public: T get() { + using namespace std::chrono_literals; + while (future.wait_for(0s) == std::future_status::timeout) { + assist(); + } return future.get(); } protected: + WorkItemT(Worker * worker) : WorkItem {worker} { } + std::promise promise; std::future future {promise.get_future()}; friend Worker; @@ -48,7 +62,10 @@ public: private: template class WorkItemTImpl : public WorkItemT { public: - WorkItemTImpl(Params &&... params) : params {std::forward(params)...} { } + WorkItemTImpl(Worker * worker, Params &&... params) : + WorkItemT {worker}, params {std::forward(params)...} + { + } private: void @@ -84,13 +101,14 @@ private: addWorkImpl(Params &&... params) { using T = decltype(std::invoke(std::forward(params)...)); - auto work = std::make_shared>(std::forward(params)...); + auto work = std::make_shared>(this, std::forward(params)...); addWorkPtr(work); return work; } void addWorkPtr(WorkPtr w); void worker(); + void assist(); using Threads = std::vector; using ToDo = std::deque; -- cgit v1.2.3