prevent race condition in isIdle

This commit is contained in:
Erik Bročko 2022-05-30 15:36:50 +02:00
parent 2f3c407944
commit 83481c54e0
Signed by: ericek111
GPG Key ID: 414DED726771329C
2 changed files with 26 additions and 5 deletions

View File

@ -119,9 +119,13 @@ private:
return;
}
auto callable = std::move(queue.pop());
if (callable.has_value()) {
// Prevent possible race condition in isIdle().
// Perhaps can be reworked, e. g. by having each worker track its progress individually?
auto callable = std::move(queue.pop([&] {
threadsWorking++;
}));
if (callable.has_value()) {
callable.value()();
threadsWorking--;
poolCond.notify_all();

View File

@ -17,6 +17,13 @@ template <typename T>
class SafePriorityQueue {
public:
/*
* Default value for functor-taking methods.
*/
struct no_op {
constexpr void operator()() const { }
};
void push(int priority, T& obj)
{
push(priority, std::forward<T>(obj));
@ -41,7 +48,15 @@ public:
queueLength++;
}
std::optional<T> pop()
/**
* Pop (and return) the top-most item in the stack.
* @tparam F
* @param callback Will be executed after (and only after) an element is popped off the queue,
* but before the mutex is released -- good for count-keeping.
* @return If the queue is empty, std::nullopt is returned.
*/
template <typename F = no_op>
std::optional<T> pop(F&& callback = no_op())
{
std::unique_lock<std::shared_mutex> lock(mtx);
@ -51,10 +66,12 @@ public:
queueLength--;
auto ret = std::move(queue.front());
auto ret = std::move(queue.front().second);
queue.pop_front();
return ret.second;
callback();
return ret;
}
std::optional<T> peek() const