clang-tools 20.0.0git
TUScheduler.h
Go to the documentation of this file.
1//===--- TUScheduler.h -------------------------------------------*-C++-*-===//
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#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_TUSCHEDULER_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_TUSCHEDULER_H
11
12#include "ASTSignals.h"
13#include "Compiler.h"
14#include "Diagnostics.h"
16#include "clang-include-cleaner/Record.h"
17#include "support/Function.h"
18#include "support/MemoryTree.h"
19#include "support/Path.h"
20#include "support/Threading.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
23#include <chrono>
24#include <memory>
25#include <optional>
26#include <string>
27
28namespace clang {
29namespace clangd {
30class ParsedAST;
31struct PreambleData;
32
33/// Returns a number of a default async threads to use for TUScheduler.
34/// Returned value is always >= 1 (i.e. will not cause requests to be processed
35/// synchronously).
37
41};
42
44 llvm::StringRef Contents;
45 const tooling::CompileCommand &Command;
46 // This can be nullptr if no preamble is available.
48 // This can be nullptr if no ASTSignals are available.
50};
51
52/// Determines whether diagnostics should be generated for a file snapshot.
53enum class WantDiagnostics {
54 Yes, /// Diagnostics must be generated for this snapshot.
55 No, /// Diagnostics must not be generated for this snapshot.
56 Auto, /// Diagnostics must be generated for this snapshot or a subsequent one,
57 /// within a bounded amount of time.
58};
59
60/// Configuration of the AST retention policy. This only covers retention of
61/// *idle* ASTs. If queue has operations requiring the AST, they might be
62/// kept in memory.
64 /// Maximum number of ASTs to be retained in memory when there are no pending
65 /// requests for them.
66 unsigned MaxRetainedASTs = 3;
67};
68
69/// Clangd may wait after an update to see if another one comes along.
70/// This is so we rebuild once the user stops typing, not when they start.
71/// Debounce may be disabled/interrupted if we must build this version.
72/// The debounce time is responsive to user preferences and rebuild time.
73/// In the future, we could also consider different types of edits.
75 using clock = std::chrono::steady_clock;
76
77 /// The minimum time that we always debounce for.
78 clock::duration Min = /*zero*/ {};
79 /// The maximum time we may debounce for.
80 clock::duration Max = /*zero*/ {};
81 /// Target debounce, as a fraction of file rebuild time.
82 /// e.g. RebuildRatio = 2, recent builds took 200ms => debounce for 400ms.
83 float RebuildRatio = 1;
84
85 /// Compute the time to debounce based on this policy and recent build times.
86 clock::duration compute(llvm::ArrayRef<clock::duration> History) const;
87 /// A policy that always returns the same duration, useful for tests.
88 static DebouncePolicy fixed(clock::duration);
89};
90
91/// PreambleThrottler controls which preambles can build at any given time.
92/// This can be used to limit overall concurrency, and to prioritize some
93/// preambles over others.
94/// In a distributed environment, a throttler may be able to coordinate resource
95/// use across several clangd instances.
96///
97/// This class is threadsafe.
99public:
100 virtual ~PreambleThrottler() = default;
101
102 using RequestID = unsigned;
103 using Callback = llvm::unique_function<void()>;
104 /// Attempt to acquire resources to build a file's preamble.
105 ///
106 /// Does not block, may eventually invoke the callback to satisfy the request.
107 /// If the callback is invoked, release() must be called afterwards.
108 virtual RequestID acquire(llvm::StringRef Filename, Callback) = 0;
109 /// Abandons the request/releases any resources that have been acquired.
110 ///
111 /// Must be called exactly once after acquire().
112 /// acquire()'s callback will not be invoked after release() returns.
113 virtual void release(RequestID) = 0;
114
115 // FIXME: we may want to be able attach signals to filenames.
116 // this would allow the throttler to make better scheduling decisions.
117};
118
119enum class PreambleAction {
120 Queued,
121 Building,
122 Idle,
123};
124
125struct ASTAction {
126 enum Kind {
127 Queued, // The action is pending in the thread task queue to be run.
128 RunningAction, // Started running actions on the TU.
129 Building, // The AST is being built.
130 Idle, // Indicates the worker thread is idle, and ready to run any upcoming
131 // actions.
132 };
133 ASTAction() = default;
134 ASTAction(Kind K, llvm::StringRef Name) : K(K), Name(Name) {}
136 /// The name of the action currently running, e.g. Update, GoToDef, Hover.
137 /// Empty if we are in the idle state.
138 std::string Name;
139};
140
141// Internal status of the TU in TUScheduler.
142struct TUStatus {
144 /// Indicates whether clang failed to build the TU.
145 bool BuildFailed = false;
146 /// Indicates whether we reused the prebuilt AST.
147 bool ReuseAST = false;
148 };
149 /// Serialize this to an LSP file status item.
151
154 /// Stores status of the last build for the translation unit.
156};
157
159public:
160 virtual ~ParsingCallbacks() = default;
161
162 /// Called on the AST that was built for emitting the preamble. The built AST
163 /// contains only AST nodes from the #include directives at the start of the
164 /// file. AST node in the current file should be observed on onMainAST call.
165 virtual void
166 onPreambleAST(PathRef Path, llvm::StringRef Version, CapturedASTCtx Ctx,
167 std::shared_ptr<const include_cleaner::PragmaIncludes>) {}
168 /// The argument function is run under the critical section guarding against
169 /// races when closing the files.
170 using PublishFn = llvm::function_ref<void(llvm::function_ref<void()>)>;
171 /// Called on the AST built for the file itself. Note that preamble AST nodes
172 /// are not deserialized and should be processed in the onPreambleAST call
173 /// instead.
174 /// The \p AST always contains all AST nodes for the main file itself, and
175 /// only a portion of the AST nodes deserialized from the preamble. Note that
176 /// some nodes from the preamble may have been deserialized and may also be
177 /// accessed from the main file AST, e.g. redecls of functions from preamble,
178 /// etc. Clients are expected to process only the AST nodes from the main file
179 /// in this callback (obtained via ParsedAST::getLocalTopLevelDecls) to obtain
180 /// optimal performance.
181 ///
182 /// When information about the file (e.g. diagnostics) is
183 /// published to clients, this should be wrapped in Publish, e.g.
184 /// void onMainAST(...) {
185 /// Diags = renderDiagnostics();
186 /// Publish([&] { notifyDiagnostics(Path, Diags); });
187 /// }
188 /// This guarantees that clients will see results in the correct sequence if
189 /// the file is concurrently closed and/or reopened. (The lambda passed to
190 /// Publish() may never run in this case).
191 virtual void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish) {}
192
193 /// Called whenever the AST fails to build. \p Diags will have the diagnostics
194 /// that led to failure.
195 virtual void onFailedAST(PathRef Path, llvm::StringRef Version,
196 std::vector<Diag> Diags, PublishFn Publish) {}
197
198 /// Called whenever the TU status is updated.
199 virtual void onFileUpdated(PathRef File, const TUStatus &Status) {}
200
201 /// Preamble for the TU have changed. This might imply new semantics (e.g.
202 /// different highlightings). Any actions on the file are guranteed to see new
203 /// preamble after the callback.
205};
206
207/// Handles running tasks for ClangdServer and managing the resources (e.g.,
208/// preambles and ASTs) for opened files.
209/// TUScheduler is not thread-safe, only one thread should be providing updates
210/// and scheduling tasks.
211/// Callbacks are run on a threadpool and it's appropriate to do slow work in
212/// them. Each task has a name, used for tracing (should be UpperCamelCase).
214public:
215 struct Options {
216 /// Number of concurrent actions.
217 /// Governs per-file worker threads and threads spawned for other tasks.
218 /// (This does not prevent threads being spawned, but rather blocks them).
219 /// If 0, executes actions synchronously on the calling thread.
221
222 /// Cache (large) preamble data in RAM rather than temporary files on disk.
224
225 /// Time to wait after an update to see if another one comes along.
226 /// This tries to ensure we rebuild once the user stops typing.
228
229 /// Determines when to keep idle ASTs in memory for future use.
231
232 /// This throttler controls which preambles may be built at a given time.
234
235 /// Used to create a context that wraps each single operation.
236 /// Typically to inject per-file configuration.
237 /// If the path is empty, context sholud be "generic".
239 };
240
241 TUScheduler(const GlobalCompilationDatabase &CDB, const Options &Opts,
242 std::unique_ptr<ParsingCallbacks> ASTCallbacks = nullptr);
243 ~TUScheduler();
244
245 struct FileStats {
246 std::size_t UsedBytesAST = 0;
247 std::size_t UsedBytesPreamble = 0;
248 unsigned PreambleBuilds = 0;
249 unsigned ASTBuilds = 0;
250 };
251 /// Returns resources used for each of the currently open files.
252 /// Results are inherently racy as they measure activity of other threads.
253 llvm::StringMap<FileStats> fileStats() const;
254
255 /// Returns a list of files with ASTs currently stored in memory. This method
256 /// is not very reliable and is only used for test. E.g., the results will not
257 /// contain files that currently run something over their AST.
258 std::vector<Path> getFilesWithCachedAST() const;
259
260 /// Schedule an update for \p File.
261 /// The compile command in \p Inputs is ignored; worker queries CDB to get
262 /// the actual compile command.
263 /// If diagnostics are requested (Yes), and the context is cancelled
264 /// before they are prepared, they may be skipped if eventual-consistency
265 /// permits it (i.e. WantDiagnostics is downgraded to Auto).
266 /// Returns true if the file was not previously tracked.
268
269 /// Remove \p File from the list of tracked files and schedule removal of its
270 /// resources. Pending diagnostics for closed files may not be delivered, even
271 /// if requested with WantDiags::Auto or WantDiags::Yes.
272 void remove(PathRef File);
273
274 /// Schedule an async task with no dependencies.
275 /// Path may be empty (it is used only to set the Context).
276 void run(llvm::StringRef Name, llvm::StringRef Path,
277 llvm::unique_function<void()> Action);
278
279 /// Similar to run, except the task is expected to be quick.
280 /// This function will not honor AsyncThreadsCount (except
281 /// if threading is disabled with AsyncThreadsCount=0)
282 /// It is intended to run quick tasks that need to run ASAP
283 void runQuick(llvm::StringRef Name, llvm::StringRef Path,
284 llvm::unique_function<void()> Action);
285
286 /// Defines how a runWithAST action is implicitly cancelled by other actions.
288 /// The request will run unless explicitly cancelled.
290 /// The request will be implicitly cancelled by a subsequent update().
291 /// (Only if the request was not yet cancelled).
292 /// Useful for requests that are generated by clients, without any explicit
293 /// user action. These can otherwise e.g. force every version to be built.
295 };
296
297 /// Schedule an async read of the AST. \p Action will be called when AST is
298 /// ready. The AST passed to \p Action refers to the version of \p File
299 /// tracked at the time of the call, even if new updates are received before
300 /// \p Action is executed.
301 /// If an error occurs during processing, it is forwarded to the \p Action
302 /// callback.
303 /// If the context is cancelled before the AST is ready, or the invalidation
304 /// policy is triggered, the callback will receive a CancelledError.
305 void runWithAST(llvm::StringRef Name, PathRef File,
308
309 /// Controls whether preamble reads wait for the preamble to be up-to-date.
311 /// The preamble may be generated from an older version of the file.
312 /// Reading from locations in the preamble may cause files to be re-read.
313 /// This gives callers two options:
314 /// - validate that the preamble is still valid, and only use it if so
315 /// - accept that the preamble contents may be outdated, and try to avoid
316 /// reading source code from headers.
317 /// This is the fastest option, usually a preamble is available immediately.
319 /// Besides accepting stale preamble, this also allow preamble to be absent
320 /// (not ready or failed to build).
322 };
323
324 /// Schedule an async read of the preamble.
325 /// If there's no up-to-date preamble, we follow the PreambleConsistency
326 /// policy.
327 /// If an error occurs, it is forwarded to the \p Action callback.
328 /// Context cancellation is ignored and should be handled by the Action.
329 /// (In practice, the Action is almost always executed immediately).
330 void runWithPreamble(llvm::StringRef Name, PathRef File,
331 PreambleConsistency Consistency,
333
334 /// Wait until there are no scheduled or running tasks.
335 /// Mostly useful for synchronizing tests.
336 bool blockUntilIdle(Deadline D) const;
337
338private:
339 /// This class stores per-file data in the Files map.
340 struct FileData;
341
342public:
343 /// Responsible for retaining and rebuilding idle ASTs. An implementation is
344 /// an LRU cache.
345 class ASTCache;
346 /// Tracks headers included by open files, to get known-good compile commands.
347 class HeaderIncluderCache;
348
349 // The file being built/processed in the current thread. This is a hack in
350 // order to get the file name into the index implementations. Do not depend on
351 // this inside clangd.
352 // FIXME: remove this when there is proper index support via build system
353 // integration.
354 // FIXME: move to ClangdServer via createProcessingContext.
355 static std::optional<llvm::StringRef> getFileBeingProcessedInContext();
356
357 void profile(MemoryTree &MT) const;
358
359private:
360 void runWithSemaphore(llvm::StringRef Name, llvm::StringRef Path,
361 llvm::unique_function<void()> Action, Semaphore &Sem);
362
363 const GlobalCompilationDatabase &CDB;
364 Options Opts;
365 std::unique_ptr<ParsingCallbacks> Callbacks; // not nullptr
366 Semaphore Barrier;
367 Semaphore QuickRunBarrier;
368 llvm::StringMap<std::unique_ptr<FileData>> Files;
369 std::unique_ptr<ASTCache> IdleASTs;
370 std::unique_ptr<HeaderIncluderCache> HeaderIncluders;
371 // std::nullopt when running tasks synchronously and non-std::nullopt when
372 // running tasks asynchronously.
373 std::optional<AsyncTaskRunner> PreambleTasks;
374 std::optional<AsyncTaskRunner> WorkerThreads;
375 // Used to create contexts for operations that are not bound to a particular
376 // file (e.g. index queries).
377 std::string LastActiveFile;
378};
379
380} // namespace clangd
381} // namespace clang
382
383#endif
llvm::SmallString< 256U > Name
std::string Filename
Filename as a string.
FieldAction Action
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
A point in time we can wait for.
Definition: Threading.h:46
Provides compilation arguments used for parsing C and C++ files.
Stores and provides access to parsed AST.
Definition: ParsedAST.h:46
virtual void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish)
Called on the AST built for the file itself.
Definition: TUScheduler.h:191
virtual void onPreambleAST(PathRef Path, llvm::StringRef Version, CapturedASTCtx Ctx, std::shared_ptr< const include_cleaner::PragmaIncludes >)
Called on the AST that was built for emitting the preamble.
Definition: TUScheduler.h:166
virtual void onPreamblePublished(PathRef File)
Preamble for the TU have changed.
Definition: TUScheduler.h:204
virtual void onFileUpdated(PathRef File, const TUStatus &Status)
Called whenever the TU status is updated.
Definition: TUScheduler.h:199
virtual ~ParsingCallbacks()=default
llvm::function_ref< void(llvm::function_ref< void()>)> PublishFn
The argument function is run under the critical section guarding against races when closing the files...
Definition: TUScheduler.h:170
virtual void onFailedAST(PathRef Path, llvm::StringRef Version, std::vector< Diag > Diags, PublishFn Publish)
Called whenever the AST fails to build.
Definition: TUScheduler.h:195
PreambleThrottler controls which preambles can build at any given time.
Definition: TUScheduler.h:98
llvm::unique_function< void()> Callback
Definition: TUScheduler.h:103
virtual ~PreambleThrottler()=default
virtual RequestID acquire(llvm::StringRef Filename, Callback)=0
Attempt to acquire resources to build a file's preamble.
virtual void release(RequestID)=0
Abandons the request/releases any resources that have been acquired.
Limits the number of threads that can acquire the lock at the same time.
Definition: Threading.h:29
Handles running tasks for ClangdServer and managing the resources (e.g., preambles and ASTs) for open...
Definition: TUScheduler.h:213
void runWithPreamble(llvm::StringRef Name, PathRef File, PreambleConsistency Consistency, Callback< InputsAndPreamble > Action)
Schedule an async read of the preamble.
void remove(PathRef File)
Remove File from the list of tracked files and schedule removal of its resources.
static std::optional< llvm::StringRef > getFileBeingProcessedInContext()
std::vector< Path > getFilesWithCachedAST() const
Returns a list of files with ASTs currently stored in memory.
llvm::StringMap< FileStats > fileStats() const
Returns resources used for each of the currently open files.
void profile(MemoryTree &MT) const
bool blockUntilIdle(Deadline D) const
Wait until there are no scheduled or running tasks.
bool update(PathRef File, ParseInputs Inputs, WantDiagnostics WD)
Schedule an update for File.
PreambleConsistency
Controls whether preamble reads wait for the preamble to be up-to-date.
Definition: TUScheduler.h:310
@ StaleOrAbsent
Besides accepting stale preamble, this also allow preamble to be absent (not ready or failed to build...
Definition: TUScheduler.h:321
@ Stale
The preamble may be generated from an older version of the file.
Definition: TUScheduler.h:318
void runQuick(llvm::StringRef Name, llvm::StringRef Path, llvm::unique_function< void()> Action)
Similar to run, except the task is expected to be quick.
ASTActionInvalidation
Defines how a runWithAST action is implicitly cancelled by other actions.
Definition: TUScheduler.h:287
@ NoInvalidation
The request will run unless explicitly cancelled.
Definition: TUScheduler.h:289
@ InvalidateOnUpdate
The request will be implicitly cancelled by a subsequent update().
Definition: TUScheduler.h:294
void runWithAST(llvm::StringRef Name, PathRef File, Callback< InputsAndAST > Action, ASTActionInvalidation=NoInvalidation)
Schedule an async read of the AST.
unsigned getDefaultAsyncThreadsCount()
Returns a number of a default async threads to use for TUScheduler.
std::string Path
A typedef to represent a file path.
Definition: Path.h:26
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
WantDiagnostics
Determines whether diagnostics should be generated for a file snapshot.
Definition: TUScheduler.h:53
@ Auto
Diagnostics must not be generated for this snapshot.
@ No
Diagnostics must be generated for this snapshot.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
-clang-tidy
std::string Name
The name of the action currently running, e.g.
Definition: TUScheduler.h:138
ASTAction(Kind K, llvm::StringRef Name)
Definition: TUScheduler.h:134
Configuration of the AST retention policy.
Definition: TUScheduler.h:63
unsigned MaxRetainedASTs
Maximum number of ASTs to be retained in memory when there are no pending requests for them.
Definition: TUScheduler.h:66
Signals derived from a valid AST of a file.
Definition: ASTSignals.h:27
The captured AST context.
Definition: Preamble.h:59
Clangd may wait after an update to see if another one comes along.
Definition: TUScheduler.h:74
clock::duration compute(llvm::ArrayRef< clock::duration > History) const
Compute the time to debounce based on this policy and recent build times.
float RebuildRatio
Target debounce, as a fraction of file rebuild time.
Definition: TUScheduler.h:83
clock::duration Min
The minimum time that we always debounce for.
Definition: TUScheduler.h:78
clock::duration Max
The maximum time we may debounce for.
Definition: TUScheduler.h:80
static DebouncePolicy fixed(clock::duration)
A policy that always returns the same duration, useful for tests.
std::chrono::steady_clock clock
Definition: TUScheduler.h:75
Clangd extension: indicates the current state of the file in clangd, sent from server via the textDoc...
Definition: Protocol.h:1790
const ParseInputs & Inputs
Definition: TUScheduler.h:39
const tooling::CompileCommand & Command
Definition: TUScheduler.h:45
const PreambleData * Preamble
Definition: TUScheduler.h:47
const ASTSignals * Signals
Definition: TUScheduler.h:49
A tree that can be used to represent memory usage of nested components while preserving the hierarchy...
Definition: MemoryTree.h:30
Information required to run clang, e.g. to parse AST or do code completion.
Definition: Compiler.h:49
The parsed preamble and associated data.
Definition: Preamble.h:97
ASTRetentionPolicy RetentionPolicy
Determines when to keep idle ASTs in memory for future use.
Definition: TUScheduler.h:230
DebouncePolicy UpdateDebounce
Time to wait after an update to see if another one comes along.
Definition: TUScheduler.h:227
std::function< Context(PathRef)> ContextProvider
Used to create a context that wraps each single operation.
Definition: TUScheduler.h:238
bool StorePreamblesInMemory
Cache (large) preamble data in RAM rather than temporary files on disk.
Definition: TUScheduler.h:223
unsigned AsyncThreadsCount
Number of concurrent actions.
Definition: TUScheduler.h:220
bool ReuseAST
Indicates whether we reused the prebuilt AST.
Definition: TUScheduler.h:147
bool BuildFailed
Indicates whether clang failed to build the TU.
Definition: TUScheduler.h:145
FileStatus render(PathRef File) const
Serialize this to an LSP file status item.
PreambleAction PreambleActivity
Definition: TUScheduler.h:152
BuildDetails Details
Stores status of the last build for the translation unit.
Definition: TUScheduler.h:155