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>:: > value, > + "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