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 >> > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits