[clang-tools-extra] r315210 - [clangd] Added move-only function helpers.

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 10 01:28:55 PDT 2017


Will do, sorry about that.

On Oct 10, 2017 01:15, "Galina Kistanova" <gkistanova at gmail.com> wrote:

> 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>::v
>> alue,
>> +        "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/20171010/ec217171/attachment-0001.html>


More information about the cfe-commits mailing list