[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