Index: clangd/ClangdServer.h =================================================================== --- clangd/ClangdServer.h +++ clangd/ClangdServer.h @@ -252,6 +252,14 @@ llvm::Optional OverridenContents = llvm::None, IntrusiveRefCntPtr *UsedFS = nullptr); + /// A version of `codeComplete` that runs \p Callback on the processing thread + /// when codeComplete results become available. + void codeComplete( + UniqueFunction>)> Callback, + PathRef File, Position Pos, + llvm::Optional OverridenContents = llvm::None, + IntrusiveRefCntPtr *UsedFS = nullptr); + /// Provide signature help for \p File at \p Pos. If \p OverridenContents is /// not None, they will used only for signature help, i.e. no diagnostics /// update will be scheduled and a draft for \p File will not be updated. If Index: clangd/ClangdServer.cpp =================================================================== --- clangd/ClangdServer.cpp +++ clangd/ClangdServer.cpp @@ -48,6 +48,25 @@ return CompilerInvocation::GetResourcesPath("clangd", (void *)&Dummy); } +template +std::future makeFutureAPIFromCallback( + ClangdServer *Server, + void (ClangdServer::*CallbackFunPtr)(UniqueFunction, Args...), + Args... As) { + std::promise ResultPromise; + std::future ResultFuture = ResultPromise.get_future(); + + auto Callback = [](std::promise ResultPromise, Ret Result) -> void { + ResultPromise.set_value(std::move(Result)); + }; + + (Server->*CallbackFunPtr)( + BindWithForward(std::move(Callback), std::move(ResultPromise)), + std::forward(As)...); + + return ResultFuture; +} + } // namespace size_t clangd::positionToOffset(StringRef Code, Position P) { @@ -198,6 +217,17 @@ ClangdServer::codeComplete(PathRef File, Position Pos, llvm::Optional OverridenContents, IntrusiveRefCntPtr *UsedFS) { + return makeFutureAPIFromCallback(this, &ClangdServer::codeComplete, File, Pos, + OverridenContents, UsedFS); +} + +void ClangdServer::codeComplete( + UniqueFunction>)> Callback, + PathRef File, Position Pos, llvm::Optional OverridenContents, + IntrusiveRefCntPtr *UsedFS) { + using CallbackType = + UniqueFunction>)>; + std::string Contents; if (OverridenContents) { Contents = *OverridenContents; @@ -216,36 +246,33 @@ std::shared_ptr Resources = Units.getFile(File); assert(Resources && "Calling completion on non-added file"); - using PackagedTask = - std::packaged_task>()>; - // Remember the current Preamble and use it when async task starts executing. // At the point when async task starts executing, we may have a different // Preamble in Resources. However, we assume the Preamble that we obtain here // is reusable in completion more often. std::shared_ptr Preamble = Resources->getPossiblyStalePreamble(); - // A task that will be run asynchronously. - PackagedTask Task([=]() mutable { // 'mutable' to reassign Preamble variable. - if (!Preamble) { - // Maybe we built some preamble before processing this request. - Preamble = Resources->getPossiblyStalePreamble(); - } - // FIXME(ibiryukov): even if Preamble is non-null, we may want to check - // both the old and the new version in case only one of them matches. - - std::vector Result = clangd::codeComplete( - File, Resources->getCompileCommand(), - Preamble ? &Preamble->Preamble : nullptr, Contents, Pos, TaggedFS.Value, - PCHs, SnippetCompletions, Logger); - return make_tagged(std::move(Result), std::move(TaggedFS.Tag)); - }); - auto Future = Task.get_future(); - // FIXME(ibiryukov): to reduce overhead for wrapping the same callable - // multiple times, ClangdScheduler should return future<> itself. - WorkScheduler.addToFront([](PackagedTask Task) { Task(); }, std::move(Task)); - return Future; + // A task that will be run asynchronously. + auto Task = + // 'mutable' to reassign Preamble variable. + [=](CallbackType Callback) mutable { + if (!Preamble) { + // Maybe we built some preamble before processing this request. + Preamble = Resources->getPossiblyStalePreamble(); + } + // FIXME(ibiryukov): even if Preamble is non-null, we may want to check + // both the old and the new version in case only one of them matches. + + std::vector Result = clangd::codeComplete( + File, Resources->getCompileCommand(), + Preamble ? &Preamble->Preamble : nullptr, Contents, Pos, + TaggedFS.Value, PCHs, SnippetCompletions, Logger); + + Callback(make_tagged(std::move(Result), std::move(TaggedFS.Tag))); + }; + + WorkScheduler.addToFront(std::move(Task), std::move(Callback)); } Tagged