[clangd] Replace UniqueFunction with llvm::unique_function.

One implementation of this ought to be enough for everyone.

llvm-svn: 336228
This commit is contained in:
Benjamin Kramer 2018-07-03 20:59:33 +00:00
parent 2f0dd1405e
commit c36c09fe8e
9 changed files with 29 additions and 84 deletions

View File

@ -280,7 +280,7 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
}
void ClangdServer::dumpAST(PathRef File,
UniqueFunction<void(std::string)> Callback) {
llvm::unique_function<void(std::string)> Callback) {
auto Action = [](decltype(Callback) Callback,
llvm::Expected<InputsAndAST> InpAST) {
if (!InpAST) {

View File

@ -188,7 +188,7 @@ public:
/// Only for testing purposes.
/// Waits until all requests to worker thread are finished and dumps AST for
/// \p File. \p File must be in the list of added documents.
void dumpAST(PathRef File, UniqueFunction<void(std::string)> Callback);
void dumpAST(PathRef File, llvm::unique_function<void(std::string)> Callback);
/// Called when an event occurs for a watched file in the workspace.
void onFileEvent(const DidChangeWatchedFilesParams &Params);

View File

@ -566,7 +566,7 @@ static bool isBlacklistedMember(const NamedDecl &D) {
// within the callback.
struct CompletionRecorder : public CodeCompleteConsumer {
CompletionRecorder(const CodeCompleteOptions &Opts,
UniqueFunction<void()> ResultsCallback)
llvm::unique_function<void()> ResultsCallback)
: CodeCompleteConsumer(Opts.getClangCompleteOpts(),
/*OutputIsBinary=*/false),
CCContext(CodeCompletionContext::CCC_Other), Opts(Opts),
@ -657,7 +657,7 @@ private:
CodeCompleteOptions Opts;
std::shared_ptr<GlobalCodeCompletionAllocator> CCAllocator;
CodeCompletionTUInfo CCTUInfo;
UniqueFunction<void()> ResultsCallback;
llvm::unique_function<void()> ResultsCallback;
};
class SignatureHelpCollector final : public CodeCompleteConsumer {

View File

@ -7,83 +7,25 @@
//
//===----------------------------------------------------------------------===//
//
// This file provides an analogue to std::function that supports move semantics.
// This file provides utilities for callable objects.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/Support/Error.h"
#include <cassert>
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
namespace clang {
namespace clangd {
/// A move-only type-erasing function wrapper. Similar to `std::function`, but
/// allows to store move-only callables.
template <class> class UniqueFunction;
/// A Callback<T> is a void function that accepts Expected<T>.
/// This is accepted by ClangdServer functions that logically return T.
template <typename T> using Callback = UniqueFunction<void(llvm::Expected<T>)>;
template <class Ret, class... Args> class UniqueFunction<Ret(Args...)> {
public:
UniqueFunction() = default;
UniqueFunction(std::nullptr_t) : UniqueFunction(){};
UniqueFunction(UniqueFunction const &) = delete;
UniqueFunction &operator=(UniqueFunction const &) = delete;
UniqueFunction(UniqueFunction &&) noexcept = default;
UniqueFunction &operator=(UniqueFunction &&) noexcept = default;
template <class Callable,
/// A sfinae-check that Callable can be called with Args... and
class = typename std::enable_if<std::is_convertible<
decltype(std::declval<Callable>()(std::declval<Args>()...)),
Ret>::value>::type>
UniqueFunction(Callable &&Func)
: CallablePtr(llvm::make_unique<
FunctionCallImpl<typename std::decay<Callable>::type>>(
std::forward<Callable>(Func))) {}
explicit operator bool() { return bool(CallablePtr); }
Ret operator()(Args... As) {
assert(CallablePtr);
return CallablePtr->Call(std::forward<Args>(As)...);
}
private:
class FunctionCallBase {
public:
virtual ~FunctionCallBase() = default;
virtual Ret Call(Args... As) = 0;
};
template <class Callable>
class FunctionCallImpl final : public FunctionCallBase {
static_assert(
std::is_same<Callable, typename std::decay<Callable>::type>::value,
"FunctionCallImpl must be instanstiated with std::decay'ed types");
public:
FunctionCallImpl(Callable Func) : Func(std::move(Func)) {}
Ret Call(Args... As) override { return Func(std::forward<Args>(As)...); }
private:
Callable Func;
};
std::unique_ptr<FunctionCallBase> CallablePtr;
};
template <typename T>
using Callback = llvm::unique_function<void(llvm::Expected<T>)>;
/// Stores a callable object (Func) and arguments (Args) and allows to call the
/// callable with provided arguments later using `operator ()`. The arguments

View File

@ -169,9 +169,10 @@ public:
~ASTWorker();
void update(ParseInputs Inputs, WantDiagnostics,
UniqueFunction<void(std::vector<Diag>)> OnUpdated);
void runWithAST(llvm::StringRef Name,
UniqueFunction<void(llvm::Expected<InputsAndAST>)> Action);
llvm::unique_function<void(std::vector<Diag>)> OnUpdated);
void
runWithAST(llvm::StringRef Name,
llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action);
bool blockUntilIdle(Deadline Timeout) const;
std::shared_ptr<const PreambleData> getPossiblyStalePreamble() const;
@ -186,7 +187,7 @@ private:
/// Signal that run() should finish processing pending requests and exit.
void stop();
/// Adds a new task to the end of the request queue.
void startTask(llvm::StringRef Name, UniqueFunction<void()> Task,
void startTask(llvm::StringRef Name, llvm::unique_function<void()> Task,
llvm::Optional<WantDiagnostics> UpdateType);
/// Determines the next action to perform.
/// All actions that should never run are disarded.
@ -197,7 +198,7 @@ private:
bool shouldSkipHeadLocked() const;
struct Request {
UniqueFunction<void()> Action;
llvm::unique_function<void()> Action;
std::string Name;
steady_clock::time_point AddTime;
Context Ctx;
@ -311,8 +312,9 @@ ASTWorker::~ASTWorker() {
#endif
}
void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
UniqueFunction<void(std::vector<Diag>)> OnUpdated) {
void ASTWorker::update(
ParseInputs Inputs, WantDiagnostics WantDiags,
llvm::unique_function<void(std::vector<Diag>)> OnUpdated) {
auto Task = [=](decltype(OnUpdated) OnUpdated) mutable {
tooling::CompileCommand OldCommand = std::move(FileInputs.CompileCommand);
FileInputs = Inputs;
@ -356,7 +358,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
void ASTWorker::runWithAST(
llvm::StringRef Name,
UniqueFunction<void(llvm::Expected<InputsAndAST>)> Action) {
llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action) {
auto Task = [=](decltype(Action) Action) {
llvm::Optional<std::unique_ptr<ParsedAST>> AST = IdleASTs.take(this);
if (!AST) {
@ -411,7 +413,8 @@ void ASTWorker::stop() {
RequestsCV.notify_all();
}
void ASTWorker::startTask(llvm::StringRef Name, UniqueFunction<void()> Task,
void ASTWorker::startTask(llvm::StringRef Name,
llvm::unique_function<void()> Task,
llvm::Optional<WantDiagnostics> UpdateType) {
if (RunSync) {
assert(!Done && "running a task after stop()");
@ -586,9 +589,9 @@ bool TUScheduler::blockUntilIdle(Deadline D) const {
return true;
}
void TUScheduler::update(PathRef File, ParseInputs Inputs,
WantDiagnostics WantDiags,
UniqueFunction<void(std::vector<Diag>)> OnUpdated) {
void TUScheduler::update(
PathRef File, ParseInputs Inputs, WantDiagnostics WantDiags,
llvm::unique_function<void(std::vector<Diag>)> OnUpdated) {
std::unique_ptr<FileData> &FD = Files[File];
if (!FD) {
// Create a new worker to process the AST-related tasks.
@ -614,7 +617,7 @@ void TUScheduler::remove(PathRef File) {
void TUScheduler::runWithAST(
llvm::StringRef Name, PathRef File,
UniqueFunction<void(llvm::Expected<InputsAndAST>)> Action) {
llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action) {
auto It = Files.find(File);
if (It == Files.end()) {
Action(llvm::make_error<llvm::StringError>(
@ -628,7 +631,7 @@ void TUScheduler::runWithAST(
void TUScheduler::runWithPreamble(
llvm::StringRef Name, PathRef File,
UniqueFunction<void(llvm::Expected<InputsAndPreamble>)> Action) {
llvm::unique_function<void(llvm::Expected<InputsAndPreamble>)> Action) {
auto It = Files.find(File);
if (It == Files.end()) {
Action(llvm::make_error<llvm::StringError>(

View File

@ -79,7 +79,7 @@ public:
/// \p File was not part of it before.
/// FIXME(ibiryukov): remove the callback from this function.
void update(PathRef File, ParseInputs Inputs, WantDiagnostics WD,
UniqueFunction<void(std::vector<Diag>)> OnUpdated);
llvm::unique_function<void(std::vector<Diag>)> OnUpdated);
/// Remove \p File from the list of tracked files and schedule removal of its
/// resources.

View File

@ -51,7 +51,7 @@ bool AsyncTaskRunner::wait(Deadline D) const {
}
void AsyncTaskRunner::runAsync(llvm::Twine Name,
UniqueFunction<void()> Action) {
llvm::unique_function<void()> Action) {
{
std::lock_guard<std::mutex> Lock(Mutex);
++InFlightTasks;

View File

@ -108,7 +108,7 @@ public:
void wait() const { (void)wait(Deadline::infinity()); }
LLVM_NODISCARD bool wait(Deadline D) const;
// The name is used for tracing and debugging (e.g. to name a spawned thread).
void runAsync(llvm::Twine Name, UniqueFunction<void()> Action);
void runAsync(llvm::Twine Name, llvm::unique_function<void()> Action);
private:
mutable std::mutex Mutex;

View File

@ -36,7 +36,7 @@ template <typename T> struct CaptureProxy {
}
CaptureProxy &operator=(CaptureProxy &&) = delete;
operator UniqueFunction<void(T)>() && {
operator llvm::unique_function<void(T)>() && {
assert(!Future.valid() && "conversion to callback called multiple times");
Future = Promise.get_future();
return Bind(