prevent race condition in isIdle
This commit is contained in:
parent
2f3c407944
commit
83481c54e0
@ -119,9 +119,13 @@ private:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto callable = std::move(queue.pop());
|
// Prevent possible race condition in isIdle().
|
||||||
if (callable.has_value()) {
|
// Perhaps can be reworked, e. g. by having each worker track its progress individually?
|
||||||
|
auto callable = std::move(queue.pop([&] {
|
||||||
threadsWorking++;
|
threadsWorking++;
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (callable.has_value()) {
|
||||||
callable.value()();
|
callable.value()();
|
||||||
threadsWorking--;
|
threadsWorking--;
|
||||||
poolCond.notify_all();
|
poolCond.notify_all();
|
||||||
|
@ -17,6 +17,13 @@ template <typename T>
|
|||||||
class SafePriorityQueue {
|
class SafePriorityQueue {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*
|
||||||
|
* Default value for functor-taking methods.
|
||||||
|
*/
|
||||||
|
struct no_op {
|
||||||
|
constexpr void operator()() const { }
|
||||||
|
};
|
||||||
|
|
||||||
void push(int priority, T& obj)
|
void push(int priority, T& obj)
|
||||||
{
|
{
|
||||||
push(priority, std::forward<T>(obj));
|
push(priority, std::forward<T>(obj));
|
||||||
@ -41,7 +48,15 @@ public:
|
|||||||
queueLength++;
|
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);
|
std::unique_lock<std::shared_mutex> lock(mtx);
|
||||||
|
|
||||||
@ -51,10 +66,12 @@ public:
|
|||||||
|
|
||||||
queueLength--;
|
queueLength--;
|
||||||
|
|
||||||
auto ret = std::move(queue.front());
|
auto ret = std::move(queue.front().second);
|
||||||
queue.pop_front();
|
queue.pop_front();
|
||||||
|
|
||||||
return ret.second;
|
callback();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<T> peek() const
|
std::optional<T> peek() const
|
||||||
|
Loading…
Reference in New Issue
Block a user