clang-tools  8.0.0
Threading.cpp
Go to the documentation of this file.
1 #include "Threading.h"
2 #include "Trace.h"
3 #include "llvm/ADT/ScopeExit.h"
4 #include "llvm/Support/FormatVariadic.h"
5 #include "llvm/Support/Threading.h"
6 #include <atomic>
7 #include <thread>
8 #ifdef __USE_POSIX
9 #include <pthread.h>
10 #endif
11 
12 namespace clang {
13 namespace clangd {
14 
16  {
17  std::lock_guard<std::mutex> Lock(Mu);
18  Notified = true;
19  }
20  CV.notify_all();
21 }
22 
23 void Notification::wait() const {
24  std::unique_lock<std::mutex> Lock(Mu);
25  CV.wait(Lock, [this] { return Notified; });
26 }
27 
28 Semaphore::Semaphore(std::size_t MaxLocks) : FreeSlots(MaxLocks) {}
29 
31  std::unique_lock<std::mutex> Lock(Mutex);
32  if (FreeSlots > 0) {
33  --FreeSlots;
34  return true;
35  }
36  return false;
37 }
38 
40  trace::Span Span("WaitForFreeSemaphoreSlot");
41  // trace::Span can also acquire locks in ctor and dtor, we make sure it
42  // happens when Semaphore's own lock is not held.
43  {
44  std::unique_lock<std::mutex> Lock(Mutex);
45  SlotsChanged.wait(Lock, [&]() { return FreeSlots > 0; });
46  --FreeSlots;
47  }
48 }
49 
51  std::unique_lock<std::mutex> Lock(Mutex);
52  ++FreeSlots;
53  Lock.unlock();
54 
55  SlotsChanged.notify_one();
56 }
57 
59 
61  std::unique_lock<std::mutex> Lock(Mutex);
62  return clangd::wait(Lock, TasksReachedZero, D,
63  [&] { return InFlightTasks == 0; });
64 }
65 
66 void AsyncTaskRunner::runAsync(const llvm::Twine &Name,
67  llvm::unique_function<void()> Action) {
68  {
69  std::lock_guard<std::mutex> Lock(Mutex);
70  ++InFlightTasks;
71  }
72 
73  auto CleanupTask = llvm::make_scope_exit([this]() {
74  std::lock_guard<std::mutex> Lock(Mutex);
75  int NewTasksCnt = --InFlightTasks;
76  if (NewTasksCnt == 0) {
77  // Note: we can't unlock here because we don't want the object to be
78  // destroyed before we notify.
79  TasksReachedZero.notify_one();
80  }
81  });
82 
83  std::thread(
84  [](std::string Name, decltype(Action) Action, decltype(CleanupTask)) {
85  llvm::set_thread_name(Name);
86  Action();
87  // Make sure function stored by Action is destroyed before CleanupTask
88  // is run.
89  Action = nullptr;
90  },
91  Name.str(), std::move(Action), std::move(CleanupTask))
92  .detach();
93 }
94 
95 Deadline timeoutSeconds(llvm::Optional<double> Seconds) {
96  using namespace std::chrono;
97  if (!Seconds)
98  return Deadline::infinity();
99  return steady_clock::now() +
100  duration_cast<steady_clock::duration>(duration<double>(*Seconds));
101 }
102 
103 void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
104  Deadline D) {
105  if (D == Deadline::zero())
106  return;
107  if (D == Deadline::infinity())
108  return CV.wait(Lock);
109  CV.wait_until(Lock, D.time());
110 }
111 
112 static std::atomic<bool> AvoidThreadStarvation = {false};
113 
115  // Some *really* old glibcs are missing SCHED_IDLE.
116 #if defined(__linux__) && defined(SCHED_IDLE)
117  sched_param priority;
118  priority.sched_priority = 0;
119  pthread_setschedparam(
120  pthread_self(),
121  Priority == ThreadPriority::Low && !AvoidThreadStarvation ? SCHED_IDLE
122  : SCHED_OTHER,
123  &priority);
124 #endif
125 }
126 
127 void preventThreadStarvationInTests() { AvoidThreadStarvation = true; }
128 
129 } // namespace clangd
130 } // namespace clang
~AsyncTaskRunner()
Destructor waits for all pending tasks to finish.
Definition: Threading.cpp:58
void preventThreadStarvationInTests()
Definition: Threading.cpp:127
static std::atomic< bool > AvoidThreadStarvation
Definition: Threading.cpp:112
Semaphore(std::size_t MaxLocks)
Definition: Threading.cpp:28
void runAsync(const llvm::Twine &Name, llvm::unique_function< void()> Action)
Definition: Threading.cpp:66
static Deadline infinity()
Definition: Threading.h:63
llvm::unique_function< void()> Action
static constexpr llvm::StringLiteral Name
const Decl * D
Definition: XRefs.cpp:79
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:103
void setCurrentThreadPriority(ThreadPriority Priority)
Definition: Threading.cpp:114
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static Deadline zero()
Definition: Threading.h:62
Deadline timeoutSeconds(llvm::Optional< double > Seconds)
Makes a deadline from a timeout in seconds. None means wait forever.
Definition: Threading.cpp:95
A point in time we can wait for.
Definition: Threading.h:58
Records an event whose duration is the lifetime of the Span object.
Definition: Trace.h:83
std::chrono::steady_clock::time_point time() const
Definition: Threading.h:65