Fix endless wait in RenameThreadPool (#2675)

This commit is contained in:
UdjinM6 2019-02-01 10:49:31 +03:00 committed by GitHub
parent 1400df2e58
commit 2a330f17ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -907,18 +907,37 @@ void RenameThreadPool(ctpl::thread_pool& tp, const char* baseName)
auto cond = std::make_shared<std::condition_variable>();
auto mutex = std::make_shared<std::mutex>();
std::atomic<int> doneCnt(0);
for (size_t i = 0; i < tp.size(); i++) {
tp.push([baseName, i, cond, mutex, &doneCnt](int threadId) {
std::map<int, std::future<void> > futures;
for (int i = 0; i < tp.size(); i++) {
futures[i] = tp.push([baseName, i, cond, mutex, &doneCnt](int threadId) {
RenameThread(strprintf("%s-%d", baseName, i).c_str());
doneCnt++;
std::unique_lock<std::mutex> l(*mutex);
doneCnt++;
cond->wait(l);
});
}
while (doneCnt != tp.size()) {
do {
// Always sleep to let all threads acquire locks
MilliSleep(10);
}
// `doneCnt` should be at least `futures.size()` if tp size was increased (for whatever reason),
// or at least `tp.size()` if tp size was decreased and queue was cleared
// (which can happen on `stop()` if we were not fast enough to get all jobs to their threads).
} while (doneCnt < futures.size() && doneCnt < tp.size());
cond->notify_all();
// Make sure no one is left behind, just in case
for (auto& pair : futures) {
auto& f = pair.second;
if (f.valid() && f.wait_for(std::chrono::milliseconds(2000)) == std::future_status::timeout) {
LogPrintf("%s: %s-%d timed out\n", __func__, baseName, pair.first);
// Notify everyone again
cond->notify_all();
break;
}
}
}
void SetupEnvironment()