[clang-tools-extra] r315210 - [clangd] Added move-only function helpers.
Galina Kistanova via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 9 16:15:29 PDT 2017
Hello Ilya,
This commit broke build on one of our builders:
http://lab.llvm.org:8011/builders/clang-x86_64-linux-abi-test/builds/16435
Please have a look?
Thanks
Galina
On Mon, Oct 9, 2017 at 9:26 AM, Ilya Biryukov via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: ibiryukov
> Date: Mon Oct 9 09:26:26 2017
> New Revision: 315210
>
> URL: http://llvm.org/viewvc/llvm-project?rev=315210&view=rev
> Log:
> [clangd] Added move-only function helpers.
>
> Summary:
> They are now used in ClangdScheduler instead of deferred std::async
> computations.
> The results of `std::async` are much less effective and do not provide
> a good abstraction for similar purposes, i.e. for storing additional
> callbacks
> to clangd async tasks. The actual callback API will follow a bit later.
>
> Reviewers: klimek, bkramer, sammccall, krasimir
>
> Reviewed By: sammccall
>
> Subscribers: cfe-commits
>
> Differential Revision: https://reviews.llvm.org/D38627
>
> Added:
> clang-tools-extra/trunk/clangd/Function.h
> Modified:
> clang-tools-extra/trunk/clangd/ClangdServer.cpp
> clang-tools-extra/trunk/clangd/ClangdServer.h
>
> Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdServer.cpp?rev=315210&r1=315209&r2=315210&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
> +++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Mon Oct 9 09:26:26
> 2017
> @@ -99,7 +99,7 @@ ClangdScheduler::ClangdScheduler(unsigne
> for (unsigned I = 0; I < AsyncThreadsCount; ++I) {
> Workers.push_back(std::thread([this]() {
> while (true) {
> - std::future<void> Request;
> + UniqueFunction<void()> Request;
>
> // Pick request from the queue
> {
> @@ -120,7 +120,7 @@ ClangdScheduler::ClangdScheduler(unsigne
> RequestQueue.pop_front();
> } // unlock Mutex
>
> - Request.get();
> + Request();
> }
> }));
> }
>
> Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/ClangdServer.h?rev=315210&r1=315209&r2=315210&view=diff
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
> +++ clang-tools-extra/trunk/clangd/ClangdServer.h Mon Oct 9 09:26:26 2017
> @@ -20,6 +20,7 @@
> #include "llvm/ADT/StringRef.h"
>
> #include "ClangdUnit.h"
> +#include "Function.h"
> #include "Protocol.h"
>
> #include <condition_variable>
> @@ -132,9 +133,8 @@ public:
>
> {
> std::lock_guard<std::mutex> Lock(Mutex);
> - RequestQueue.push_front(std::async(std::launch::deferred,
> - std::forward<Func>(F),
> - std::forward<Args>(As)...));
> + RequestQueue.push_front(
> + BindWithForward(std::forward<Func>(F),
> std::forward<Args>(As)...));
> }
> RequestCV.notify_one();
> }
> @@ -149,9 +149,8 @@ public:
>
> {
> std::lock_guard<std::mutex> Lock(Mutex);
> - RequestQueue.push_back(std::async(std::launch::deferred,
> - std::forward<Func>(F),
> - std::forward<Args>(As)...));
> + RequestQueue.push_back(
> + BindWithForward(std::forward<Func>(F),
> std::forward<Args>(As)...));
> }
> RequestCV.notify_one();
> }
> @@ -167,7 +166,7 @@ private:
> bool Done = false;
> /// A queue of requests. Elements of this vector are async computations
> (i.e.
> /// results of calling std::async(std::launch::deferred, ...)).
> - std::deque<std::future<void>> RequestQueue;
> + std::deque<UniqueFunction<void()>> RequestQueue;
> /// Condition variable to wake up worker threads.
> std::condition_variable RequestCV;
> };
>
> Added: clang-tools-extra/trunk/clangd/Function.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/
> trunk/clangd/Function.h?rev=315210&view=auto
> ============================================================
> ==================
> --- clang-tools-extra/trunk/clangd/Function.h (added)
> +++ clang-tools-extra/trunk/clangd/Function.h Mon Oct 9 09:26:26 2017
> @@ -0,0 +1,136 @@
> +//===--- Function.h - Utility callable wrappers -----------------*-
> C++-*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +//
> +// This file provides an analogue to std::function that supports move
> semantics.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +
> +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
> +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FUNCTION_H
> +
> +#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;
> +
> +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>
> + UniqueFunction(Callable &&Func)
> + : CallablePtr(llvm::make_unique<
> + FunctionCallImpl<typename
> std::decay<Callable>::type>>(
> + std::forward<Callable>(Func))) {}
> +
> + operator bool() { return CallablePtr; }
> +
> + Ret operator()(Args... As) {
> + assert(CallablePtr);
> + 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;
> +};
> +
> +/// Stores a callable object (Func) and arguments (Args) and allows to
> call the
> +/// callable with provided arguments later using `operator ()`. The
> arguments
> +/// are std::forward'ed into the callable in the body of `operator()`.
> Therefore
> +/// `operator()` can only be called once, as some of the arguments could
> be
> +/// std::move'ed into the callable on first call.
> +template <class Func, class... Args> struct ForwardBinder {
> + using Tuple = std::tuple<typename std::decay<Func>::type,
> + typename std::decay<Args>::type...>;
> + Tuple FuncWithArguments;
> +#ifndef NDEBUG
> + bool WasCalled = false;
> +#endif
> +
> +public:
> + ForwardBinder(Tuple FuncWithArguments)
> + : FuncWithArguments(std::move(FuncWithArguments)) {}
> +
> +private:
> + template <std::size_t... Indexes, class... RestArgs>
> + auto CallImpl(llvm::integer_sequence<std::size_t, Indexes...> Seq,
> + RestArgs &&... Rest)
> + -> decltype(std::get<0>(this->FuncWithArguments)(
> + std::forward<Args>(std::get<Indexes +
> 1>(this->FuncWithArguments))...,
> + std::forward<RestArgs>(Rest)...)) {
> + return std::get<0>(this->FuncWithArguments)(
> + std::forward<Args>(std::get<Indexes +
> 1>(this->FuncWithArguments))...,
> + std::forward<RestArgs>(Rest)...);
> + }
> +
> +public:
> + template <class... RestArgs>
> + auto operator()(RestArgs &&... Rest)
> + -> decltype(CallImpl(llvm::index_sequence_for<Args...>(),
> + std::forward<RestArgs>(Rest)...)) {
> +
> +#ifndef NDEBUG
> + assert(!WasCalled && "Can only call result of BindWithForward once.");
> + WasCalled = true;
> +#endif
> + return CallImpl(llvm::index_sequence_for<Args...>(),
> + std::forward<RestArgs>(Rest)...);
> + }
> +};
> +
> +/// Creates an object that stores a callable (\p F) and first arguments
> to the
> +/// callable (\p As) and allows to call \p F with \Args at a later point.
> +/// Similar to std::bind, but also works with move-only \p F and \p As.
> +///
> +/// The returned object must be called no more than once, as \p As are
> +/// std::forwarded'ed (therefore can be moved) into \p F during the call.
> +template <class Func, class... Args>
> +ForwardBinder<Func, Args...> BindWithForward(Func F, Args &&... As) {
> + return ForwardBinder<Func, Args...>(
> + std::make_tuple(std::forward<Func>(F), std::forward<Args>(As)...));
> +}
> +
> +} // namespace clangd
> +} // namespace clang
> +
> +#endif
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171009/863451bc/attachment-0001.html>
More information about the cfe-commits
mailing list