diff --git a/src/pipeline.cc b/src/pipeline.cc index 8cb44561f..2adc003e4 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -206,7 +206,11 @@ bool indexer_Parse(SemaManager *completion, WorkingFiles *wfiles, Project *proje } struct RAII { - ~RAII() { stats.completed++; } + ~RAII() { + stats.completed++; + if (main_waiter) + main_waiter->cv.notify_one(); + } } raii; if (!matcher.matches(request.path)) { LOG_IF_S(INFO, loud) << "skip " << request.path; @@ -756,10 +760,13 @@ void mainLoop() { freeUnusedMemory(); has_indexed = false; } + auto progress_changed = [&last_completed]() { + return stats.completed.load(std::memory_order_relaxed) != last_completed; + }; if (backlog.empty()) - main_waiter->wait(g_quit, on_indexed, on_request); + main_waiter->waitWithCondition(g_quit, progress_changed, on_indexed, on_request); else - main_waiter->waitUntil(backlog[0].deadline, on_indexed, on_request); + main_waiter->waitUntilWithCondition(backlog[0].deadline, progress_changed, on_indexed, on_request); } } diff --git a/src/threaded_queue.hh b/src/threaded_queue.hh index da83cffea..66e504631 100644 --- a/src/threaded_queue.hh +++ b/src/threaded_queue.hh @@ -51,10 +51,20 @@ struct MultiQueueWaiter { return false; } + template + static bool shouldWake(Predicate &predicate, std::initializer_list queues) { + return predicate() || hasState(queues); + } + template bool wait(std::atomic &quit, BaseThreadQueue... queues) { + return waitWithCondition(quit, [] { return false; }, queues...); + } + + template + bool waitWithCondition(std::atomic &quit, Predicate &&predicate, BaseThreadQueue... queues) { MultiQueueLock l(queues...); while (!quit.load(std::memory_order_relaxed)) { - if (hasState({queues...})) + if (shouldWake(predicate, {queues...})) return false; cv.wait(l); } @@ -63,8 +73,14 @@ struct MultiQueueWaiter { template void waitUntil(std::chrono::steady_clock::time_point t, BaseThreadQueue... queues) { + waitUntilWithCondition(t, [] { return false; }, queues...); + } + + template + void waitUntilWithCondition(std::chrono::steady_clock::time_point t, Predicate &&predicate, + BaseThreadQueue... queues) { MultiQueueLock l(queues...); - if (!hasState({queues...})) + if (!shouldWake(predicate, {queues...})) cv.wait_until(l, t); } };