Fixed in r315284. On Tue, Oct 10, 2017 at 10:28 AM, Ilya Biryukov <ibiryu...@google.com> wrote:
> Will do, sorry about that. > > On Oct 10, 2017 01:15, "Galina Kistanova" <gkistan...@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@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@lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> >> >> -- Regards, Ilya Biryukov
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits