clang-tools  10.0.0git
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 
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 
60  {
61  std::lock_guard<std::mutex> QueueLock(Mu);
62  ShouldStop = true;
63  }
64  CV.notify_all();
65 }
66 
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 
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
static std::atomic< bool > PreventStarvation
tooling::Replacements Changes
Definition: Format.cpp:108
HTMLTag Tag
void boost(llvm::StringRef Tag, unsigned NewPriority)
static void preventThreadStarvationInTests()
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
LLVM_NODISCARD bool blockUntilIdleForTest(llvm::Optional< double > TimeoutSeconds)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Deadline timeoutSeconds(llvm::Optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
Definition: Threading.cpp:99
void append(std::vector< Task >)
A work item on the thread pool&#39;s queue.
Definition: Background.h:70
void work(std::function< void()> OnIdle=nullptr)