clang-tools 10.0.0

BackgroundQueue.cpp
Go to the documentation of this file.
1 //===-- BackgroundQueue.cpp - Task queue for background index -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "index/Background.h"
10
11 namespace clang {
12 namespace clangd {
13
14 static std::atomic<bool> PreventStarvation = {false};
15
16 void BackgroundQueue::preventThreadStarvationInTests() {
17 PreventStarvation.store(true);
18 }
19
20 void BackgroundQueue::work(std::function<void()> OnIdle) {
21 while (true) {
22 llvm::Optional<Task> Task;
23 {
24 std::unique_lock<std::mutex> Lock(Mu);
25 CV.wait(Lock, [&] { return ShouldStop || !Queue.empty(); });
26 if (ShouldStop) {
27 Queue.clear();
28 CV.notify_all();
29 return;
30 }
31 ++NumActiveTasks;
32 std::pop_heap(Queue.begin(), Queue.end());
33 Task = std::move(Queue.back());
34 Queue.pop_back();
35 }
36
37 if (Task->ThreadPri != llvm::ThreadPriority::Default &&
38 !PreventStarvation.load())
39 llvm::set_thread_priority(Task->ThreadPri);
40 Task->Run();
41 if (Task->ThreadPri != llvm::ThreadPriority::Default)
42 llvm::set_thread_priority(llvm::ThreadPriority::Default);
43
44 {
45 std::unique_lock<std::mutex> Lock(Mu);
46 if (NumActiveTasks == 1 && Queue.empty() && OnIdle) {
47 // We just finished the last item, the queue is going idle.
48 Lock.unlock();
49 OnIdle();
50 Lock.lock();
51 }
52 assert(NumActiveTasks > 0 && "before decrementing");
53 --NumActiveTasks;
54 }
55 CV.notify_all();
56 }
57 }
58
59 void BackgroundQueue::stop() {
60 {
61 std::lock_guard<std::mutex> QueueLock(Mu);
62 ShouldStop = true;
63 }
64 CV.notify_all();
65 }
66
67 void BackgroundQueue::push(Task T) {
68 {
69 std::lock_guard<std::mutex> Lock(Mu);
70 T.QueuePri = std::max(T.QueuePri, Boosts.lookup(T.Tag));
71 Queue.push_back(std::move(T));
72 std::push_heap(Queue.begin(), Queue.end());
73 }
74 CV.notify_all();
75 }
76
77 void BackgroundQueue::append(std::vector<Task> Tasks) {
78 {
79 std::lock_guard<std::mutex> Lock(Mu);
80 for (Task &T : Tasks)
81 T.QueuePri = std::max(T.QueuePri, Boosts.lookup(T.Tag));
82 std::move(Tasks.begin(), Tasks.end(), std::back_inserter(Queue));
83 std::make_heap(Queue.begin(), Queue.end());
84 }
85 CV.notify_all();
86 }
87
88 void BackgroundQueue::boost(llvm::StringRef Tag, unsigned NewPriority) {
89 std::lock_guard<std::mutex> Lock(Mu);
90 unsigned &Boost = Boosts[Tag];
91 bool Increase = NewPriority > Boost;
92 Boost = NewPriority;
93 if (!Increase)
94 return; // existing tasks unaffected
95
96 unsigned Changes = 0;
97 for (Task &T : Queue)
98 if (Tag == T.Tag && NewPriority > T.QueuePri) {
99 T.QueuePri = NewPriority;
100 ++Changes;
101 }
102 if (Changes)
103 std::make_heap(Queue.begin(), Queue.end());
104 // No need to signal, only rearranged items in the queue.
105 }
106
107 bool BackgroundQueue::blockUntilIdleForTest(
108 llvm::Optional<double> TimeoutSeconds) {
109 std::unique_lock<std::mutex> Lock(Mu);
110 return wait(Lock, CV, timeoutSeconds(TimeoutSeconds),
111 [&] { return Queue.empty() && NumActiveTasks == 0; });
112 }
113
114 } // namespace clangd
115 } // namespace clang
clang::clangd::PreventStarvation
static std::atomic< bool > PreventStarvation
Definition: BackgroundQueue.cpp:14
Changes
tooling::Replacements Changes
Definition: Format.cpp:108
Tag
HTMLTag Tag
Definition: HTMLGenerator.cpp:90
clang::clangd::BackgroundQueue::stop
void stop()
Definition: BackgroundQueue.cpp:59
clang::clangd::BackgroundQueue::Task::QueuePri
unsigned QueuePri
Definition: Background.h:75
clang::clangd::BackgroundQueue::push
void push(Task)
Definition: BackgroundQueue.cpp:67
clang::clangd::BackgroundQueue::boost
void boost(llvm::StringRef Tag, unsigned NewPriority)
Definition: BackgroundQueue.cpp:88
clang::clangd::BackgroundQueue::preventThreadStarvationInTests
static void preventThreadStarvationInTests()
Definition: BackgroundQueue.cpp:16
clang::clangd::BackgroundQueue::Task::Tag
std::string Tag
Definition: Background.h:76
clang::clangd::wait
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
Definition: Threading.cpp:107
clang::clangd::BackgroundQueue::blockUntilIdleForTest
LLVM_NODISCARD bool blockUntilIdleForTest(llvm::Optional< double > TimeoutSeconds)
Definition: BackgroundQueue.cpp:107
Background.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::timeoutSeconds
Deadline timeoutSeconds(llvm::Optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
Definition: Threading.cpp:99
clang::clangd::BackgroundQueue::append
void append(std::vector< Task >)
Definition: BackgroundQueue.cpp:77
clang::clangd::BackgroundQueue::Task
A work item on the thread pool&#39;s queue.
Definition: Background.h:70
clang::clangd::BackgroundQueue::work
void work(std::function< void()> OnIdle=nullptr)
Definition: BackgroundQueue.cpp:20