|
@@ -25,18 +25,39 @@ Processor::Processor(size_t limit) : mTasks(limit) {}
|
|
|
Processor::~Processor() { join(); }
|
|
|
|
|
|
void Processor::join() {
|
|
|
- std::unique_lock lock(mMutex);
|
|
|
- mCondition.wait(lock, [this]() { return !mPending && mTasks.empty(); });
|
|
|
+ // We need to detect situations where the thread pool does not execute a pending task at exit
|
|
|
+ std::optional<unsigned int> counter;
|
|
|
+ while (true) {
|
|
|
+ std::shared_future<void> pending;
|
|
|
+ {
|
|
|
+ std::unique_lock lock(mMutex);
|
|
|
+ if (!mPending // no pending task
|
|
|
+ || (counter && *counter == mCounter)) { // or no scheduled task after the last one
|
|
|
+
|
|
|
+ // Processing is stopped, clear everything and return
|
|
|
+ mPending.reset();
|
|
|
+ while (!mTasks.empty())
|
|
|
+ mTasks.pop();
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ pending = *mPending;
|
|
|
+ counter = mCounter;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Wait for the pending task
|
|
|
+ pending.wait();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void Processor::schedule() {
|
|
|
std::unique_lock lock(mMutex);
|
|
|
if (auto next = mTasks.tryPop()) {
|
|
|
- ThreadPool::Instance().enqueue(std::move(*next));
|
|
|
+ mPending = ThreadPool::Instance().enqueue(std::move(*next)).share();
|
|
|
+ ++mCounter;
|
|
|
} else {
|
|
|
- // No more tasks
|
|
|
- mPending = false;
|
|
|
- mCondition.notify_all();
|
|
|
+ mPending.reset(); // No more tasks
|
|
|
}
|
|
|
}
|
|
|
|