[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:55:35 PDT 2017


Fixed in r315284.

On Tue, Oct 10, 2017 at 10:28 AM, Ilya Biryukov <ibiryukov at google.com>
wrote:

> 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
>>>
>>
>>


-- 
Regards,
Ilya Biryukov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171010/b2edc050/attachment-0001.html>


More information about the cfe-commits mailing list