Index: clangd/ClangdServer.cpp =================================================================== --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -482,8 +482,15 @@ void ClangdServer::workspaceSymbols( StringRef Query, int Limit, Callback> CB) { - CB(clangd::getWorkspaceSymbols(Query, Limit, Index, - WorkspaceRoot.getValueOr(""))); + std::string QueryCopy = Query; + WorkScheduler.run( + "getWorkspaceSymbols", + Bind( + [QueryCopy, Limit, this](decltype(CB) CB) { + CB(clangd::getWorkspaceSymbols(QueryCopy, Limit, Index, + WorkspaceRoot.getValueOr(""))); + }, + std::move(CB))); } void ClangdServer::documentSymbols( Index: clangd/TUScheduler.h =================================================================== --- clangd/TUScheduler.h +++ clangd/TUScheduler.h @@ -108,6 +108,9 @@ /// resources. void remove(PathRef File); + /// Schedule an async task with no dependencies. + void run(llvm::StringRef Name, llvm::unique_function Action); + /// Schedule an async read of the AST. \p Action will be called when AST is /// ready. The AST passed to \p Action refers to the version of \p File /// tracked at the time of the call, even if new updates are received before Index: clangd/TUScheduler.cpp =================================================================== --- clangd/TUScheduler.cpp +++ clangd/TUScheduler.cpp @@ -720,6 +720,12 @@ File); } +void TUScheduler::run(StringRef Name, unique_function Action) { + if (!PreambleTasks) + return Action(); + PreambleTasks->runAsync(Name, std::move(Action)); +} + void TUScheduler::runWithAST( StringRef Name, PathRef File, unique_function)> Action) { Index: unittests/clangd/TUSchedulerTests.cpp =================================================================== --- unittests/clangd/TUSchedulerTests.cpp +++ unittests/clangd/TUSchedulerTests.cpp @@ -532,6 +532,18 @@ ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10))); } +TEST_F(TUSchedulerTests, Run) { + TUScheduler S(/*AsyncThreadsCount=*/getDefaultAsyncThreadsCount(), + /*StorePreambleInMemory=*/true, /*ASTCallbacks=*/nullptr, + /*UpdateDebounce=*/std::chrono::steady_clock::duration::zero(), + ASTRetentionPolicy()); + std::atomic Counter(0); + S.run("add 1", [&] { ++Counter; }); + S.run("add 2", [&] { Counter += 2; }); + ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10))); + EXPECT_EQ(Counter.load(), 3); +} + } // namespace } // namespace clangd } // namespace clang