9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADING_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_THREADING_H
13#include "llvm/ADT/FunctionExtras.h"
14#include "llvm/ADT/Twine.h"
17#include <condition_variable>
39 std::condition_variable SlotsChanged;
40 std::size_t FreeSlots;
48 Deadline(std::chrono::steady_clock::time_point Time)
49 : Type(Finite), Time(Time) {}
53 std::chrono::steady_clock::time_point
time()
const {
54 assert(Type == Finite);
58 return (Type == Zero) ||
59 (Type == Finite && Time < std::chrono::steady_clock::now());
62 return (Type == Other.Type) && (Type != Finite || Time == Other.Time);
66 enum Type { Zero, Infinite, Finite };
68 Deadline(
enum Type Type) :
Type(
Type) {}
70 std::chrono::steady_clock::time_point Time;
76void wait(std::unique_lock<std::mutex> &Lock, std::condition_variable &CV,
79template <
typename Func>
80[[nodiscard]]
bool wait(std::unique_lock<std::mutex> &Lock,
81 std::condition_variable &CV,
Deadline D, Func F) {
100 bool Notified =
false;
101 mutable std::condition_variable CV;
102 mutable std::mutex Mu;
119 mutable std::mutex Mutex;
120 mutable std::condition_variable TasksReachedZero;
121 std::size_t InFlightTasks = 0;
149 std::unique_ptr<std::mutex> Mu;
152 Memoize() : Mu(std::make_unique<std::mutex>()) {}
154 template <
typename T,
typename Func>
155 typename Container::mapped_type
get(T &&
Key, Func Compute)
const {
157 std::lock_guard<std::mutex> Lock(*Mu);
158 auto It = Cache.find(
Key);
159 if (It != Cache.end())
165 std::lock_guard<std::mutex> Lock(*Mu);
166 auto R = Cache.try_emplace(std::forward<T>(
Key), V);
169 return R.first->second;
187 using Stopwatch = std::chrono::steady_clock;
188 using Rep = Stopwatch::duration::rep;
191 std::atomic<Rep> Next;
196 : Period(Period.count()),
197 Next((Stopwatch::now() + Delay).time_since_epoch().count()) {}
llvm::SmallString< 256U > Name
Runs tasks on separate (detached) threads and wait for all tasks to finish.
void runAsync(const llvm::Twine &Name, llvm::unique_function< void()> Action)
~AsyncTaskRunner()
Destructor waits for all pending tasks to finish.
A context is an immutable container for per-request data that must be propagated through layers that ...
Context clone() const
Clone this context object.
static const Context & current()
Returns the context for the current thread, creating it if needed.
A point in time we can wait for.
bool operator==(const Deadline &Other) const
static Deadline infinity()
std::chrono::steady_clock::time_point time() const
Deadline(std::chrono::steady_clock::time_point Time)
Values in a Context are indexed by typed keys.
Memoize is a cache to store and reuse computation results based on a key.
Container::mapped_type get(T &&Key, Func Compute) const
A threadsafe flag that is initially clear.
Used to guard an operation that should run at most every N seconds.
bool operator()()
Returns whether the operation should run at this time.
PeriodicThrottler(Stopwatch::duration Period, Stopwatch::duration Delay={})
If Period is zero, the throttler will return true every time.
Limits the number of threads that can acquire the lock at the same time.
WithContext replaces Context::current() with a provided scope.
std::future< T > runAsync(llvm::unique_function< T()> Action)
Runs Action asynchronously with a new std::thread.
void wait(std::unique_lock< std::mutex > &Lock, std::condition_variable &CV, Deadline D)
Wait once on CV for the specified duration.
Deadline timeoutSeconds(std::optional< double > Seconds)
Makes a deadline from a timeout in seconds. std::nullopt means wait forever.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//