summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/TUScheduler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/TUScheduler.cpp')
-rw-r--r--clang-tools-extra/clangd/TUScheduler.cpp60
1 files changed, 31 insertions, 29 deletions
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index a77d226902c..bcfddb9acfa 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -249,9 +249,8 @@ private:
TUStatus Status;
Semaphore &Barrier;
- /// Whether the diagnostics for the current FileInputs were reported to the
- /// users before.
- bool DiagsWereReported = false;
+ /// Whether the 'onMainAST' callback ran for the current FileInputs.
+ bool RanASTCallback = false;
/// Guards members used by both TUScheduler and the worker thread.
mutable std::mutex Mutex;
/// File inputs, currently being used by the worker.
@@ -265,15 +264,16 @@ private:
bool Done; /* GUARDED_BY(Mutex) */
std::deque<Request> Requests; /* GUARDED_BY(Mutex) */
mutable std::condition_variable RequestsCV;
- // FIXME: rename it to better fix the current usage, we also use it to guard
- // emitting TUStatus.
- /// Guards a critical section for running the diagnostics callbacks.
- std::mutex DiagsMu;
- // Used to prevent remove document + leading to out-of-order diagnostics:
+ /// Guards the callback that publishes results of AST-related computations
+ /// (diagnostics, highlightings) and file statuses.
+ std::mutex PublishMu;
+ // Used to prevent remove document + add document races that lead to
+ // out-of-order callbacks for publishing results of onMainAST callback.
+ //
// The lifetime of the old/new ASTWorkers will overlap, but their handles
// don't. When the old handle is destroyed, the old worker will stop reporting
- // diagnostics.
- bool ReportDiagnostics = true; /* GUARDED_BY(DiagsMu) */
+ // any results to the user.
+ bool CanPublishResults = true; /* GUARDED_BY(PublishMu) */
};
/// A smart-pointer-like class that points to an active ASTWorker.
@@ -381,12 +381,12 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
std::tie(Inputs.CompileCommand, Inputs.Contents);
tooling::CompileCommand OldCommand = PrevInputs->CompileCommand;
- bool PrevDiagsWereReported = DiagsWereReported;
+ bool RanCallbackForPrevInputs = RanASTCallback;
{
std::lock_guard<std::mutex> Lock(Mutex);
FileInputs = std::make_shared<ParseInputs>(Inputs);
}
- DiagsWereReported = false;
+ RanASTCallback = false;
emitTUStatus({TUAction::BuildingPreamble, TaskName});
log("Updating file {0} with command {1}\n[{2}]\n{3}", FileName,
Inputs.CompileCommand.Heuristic,
@@ -432,10 +432,9 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
if (!CanReuseAST) {
IdleASTs.take(this); // Remove the old AST if it's still in cache.
} else {
- // Since we don't need to rebuild the AST, we might've already reported
- // the diagnostics for it.
- if (PrevDiagsWereReported) {
- DiagsWereReported = true;
+ // We don't need to rebuild the AST, check if we need to run the callback.
+ if (RanCallbackForPrevInputs) {
+ RanASTCallback = true;
// Take a shortcut and don't report the diagnostics, since they should
// not changed. All the clients should handle the lack of OnUpdated()
// call anyway to handle empty result from buildAST.
@@ -457,10 +456,10 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
return;
{
- std::lock_guard<std::mutex> Lock(DiagsMu);
+ std::lock_guard<std::mutex> Lock(PublishMu);
// No need to rebuild the AST if we won't send the diagnotics. However,
// note that we don't prevent preamble rebuilds.
- if (!ReportDiagnostics)
+ if (!CanPublishResults)
return;
}
@@ -486,14 +485,17 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags) {
// spam us with updates.
// Note *AST can still be null if buildAST fails.
if (*AST) {
- {
- std::lock_guard<std::mutex> Lock(DiagsMu);
- if (ReportDiagnostics)
- Callbacks.onDiagnostics(FileName, (*AST)->getDiagnostics());
- }
trace::Span Span("Running main AST callback");
- Callbacks.onMainAST(FileName, **AST);
- DiagsWereReported = true;
+ auto RunPublish = [&](llvm::function_ref<void()> Publish) {
+ // Ensure we only publish results from the worker if the file was not
+ // removed, making sure there are not race conditions.
+ std::lock_guard<std::mutex> Lock(PublishMu);
+ if (CanPublishResults)
+ Publish();
+ };
+
+ Callbacks.onMainAST(FileName, **AST, RunPublish);
+ RanASTCallback = true;
}
// Stash the AST in the cache for further use.
IdleASTs.put(this, std::move(*AST));
@@ -594,8 +596,8 @@ bool ASTWorker::isASTCached() const { return IdleASTs.getUsedBytes(this) != 0; }
void ASTWorker::stop() {
{
- std::lock_guard<std::mutex> Lock(DiagsMu);
- ReportDiagnostics = false;
+ std::lock_guard<std::mutex> Lock(PublishMu);
+ CanPublishResults = false;
}
{
std::lock_guard<std::mutex> Lock(Mutex);
@@ -630,9 +632,9 @@ void ASTWorker::emitTUStatus(TUAction Action,
Status.Action = std::move(Action);
if (Details)
Status.Details = *Details;
- std::lock_guard<std::mutex> Lock(DiagsMu);
+ std::lock_guard<std::mutex> Lock(PublishMu);
// Do not emit TU statuses when the ASTWorker is shutting down.
- if (ReportDiagnostics) {
+ if (CanPublishResults) {
Callbacks.onFileUpdated(FileName, Status);
}
}
OpenPOWER on IntegriCloud