<div dir="ltr">Fixed in r315284.</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 10, 2017 at 10:28 AM, Ilya Biryukov <span dir="ltr"><<a href="mailto:ibiryukov@google.com" target="_blank">ibiryukov@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">Will do, sorry about that.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Oct 10, 2017 01:15, "Galina Kistanova" <<a href="mailto:gkistanova@gmail.com" target="_blank">gkistanova@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hello Ilya,<br><br>This commit broke build on one of our builders:<br><br><a href="http://lab.llvm.org:8011/builders/clang-x86_64-linux-abi-test/builds/16435" target="_blank">http://lab.llvm.org:8011/build<wbr>ers/clang-x86_64-linux-abi-<wbr>test/builds/16435</a><br><br>Please have a look?<br><br>Thanks<br><br>Galina<br><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Oct 9, 2017 at 9:26 AM, Ilya Biryukov via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ibiryukov<br>
Date: Mon Oct  9 09:26:26 2017<br>
New Revision: 315210<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=315210&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=315210&view=rev</a><br>
Log:<br>
[clangd] Added move-only function helpers.<br>
<br>
Summary:<br>
They are now used in ClangdScheduler instead of deferred std::async<br>
computations.<br>
The results of `std::async` are much less effective and do not provide<br>
a good abstraction for similar purposes, i.e. for storing additional callbacks<br>
to clangd async tasks. The actual callback API will follow a bit later.<br>
<br>
Reviewers: klimek, bkramer, sammccall, krasimir<br>
<br>
Reviewed By: sammccall<br>
<br>
Subscribers: cfe-commits<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D38627" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3862<wbr>7</a><br>
<br>
Added:<br>
    clang-tools-extra/trunk/clangd<wbr>/Function.h<br>
Modified:<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp<br>
    clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=315210&r1=315209&r2=315210&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp?rev=31<wbr>5210&r1=315209&r2=315210&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdServer.cpp Mon Oct  9 09:26:26 2017<br>
@@ -99,7 +99,7 @@ ClangdScheduler::ClangdSchedul<wbr>er(unsigne<br>
   for (unsigned I = 0; I < AsyncThreadsCount; ++I) {<br>
     Workers.push_back(std::thread<wbr>([this]() {<br>
       while (true) {<br>
-        std::future<void> Request;<br>
+        UniqueFunction<void()> Request;<br>
<br>
         // Pick request from the queue<br>
         {<br>
@@ -120,7 +120,7 @@ ClangdScheduler::ClangdSchedul<wbr>er(unsigne<br>
           RequestQueue.pop_front();<br>
         } // unlock Mutex<br>
<br>
-        Request.get();<br>
+        Request();<br>
       }<br>
     }));<br>
   }<br>
<br>
Modified: clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=315210&r1=315209&r2=315210&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/ClangdServer.h?rev=3152<wbr>10&r1=315209&r2=315210&view=<wbr>diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h (original)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/ClangdServer.h Mon Oct  9 09:26:26 2017<br>
@@ -20,6 +20,7 @@<br>
 #include "llvm/ADT/StringRef.h"<br>
<br>
 #include "ClangdUnit.h"<br>
+#include "Function.h"<br>
 #include "Protocol.h"<br>
<br>
 #include <condition_variable><br>
@@ -132,9 +133,8 @@ public:<br>
<br>
     {<br>
       std::lock_guard<std::mutex> Lock(Mutex);<br>
-      RequestQueue.push_front(std::a<wbr>sync(std::launch::deferred,<br>
-                                         std::forward<Func>(F),<br>
-                                         std::forward<Args>(As)...));<br>
+      RequestQueue.push_front(<br>
+          BindWithForward(std::forward<F<wbr>unc>(F), std::forward<Args>(As)...));<br>
     }<br>
     RequestCV.notify_one();<br>
   }<br>
@@ -149,9 +149,8 @@ public:<br>
<br>
     {<br>
       std::lock_guard<std::mutex> Lock(Mutex);<br>
-      RequestQueue.push_back(std::as<wbr>ync(std::launch::deferred,<br>
-                                        std::forward<Func>(F),<br>
-                                        std::forward<Args>(As)...));<br>
+      RequestQueue.push_back(<br>
+          BindWithForward(std::forward<F<wbr>unc>(F), std::forward<Args>(As)...));<br>
     }<br>
     RequestCV.notify_one();<br>
   }<br>
@@ -167,7 +166,7 @@ private:<br>
   bool Done = false;<br>
   /// A queue of requests. Elements of this vector are async computations (i.e.<br>
   /// results of calling std::async(std::launch::deferr<wbr>ed, ...)).<br>
-  std::deque<std::future<void>> RequestQueue;<br>
+  std::deque<UniqueFunction<void<wbr>()>> RequestQueue;<br>
   /// Condition variable to wake up worker threads.<br>
   std::condition_variable RequestCV;<br>
 };<br>
<br>
Added: clang-tools-extra/trunk/clangd<wbr>/Function.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Function.h?rev=315210&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/clang-tools-extra/trunk/<wbr>clangd/Function.h?rev=315210&v<wbr>iew=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/clangd<wbr>/Function.h (added)<br>
+++ clang-tools-extra/trunk/clangd<wbr>/Function.h Mon Oct  9 09:26:26 2017<br>
@@ -0,0 +1,136 @@<br>
+//===--- Function.h - Utility callable wrappers  -----------------*- C++-*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+// This file provides an analogue to std::function that supports move semantics.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_<wbr>FUNCTION_H<br>
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_<wbr>FUNCTION_H<br>
+<br>
+#include <tuple><br>
+#include <type_traits><br>
+#include <utility><br>
+<br>
+namespace clang {<br>
+namespace clangd {<br>
+<br>
+/// A move-only type-erasing function wrapper. Similar to `std::function`, but<br>
+/// allows to store move-only callables.<br>
+template <class> class UniqueFunction;<br>
+<br>
+template <class Ret, class... Args> class UniqueFunction<Ret(Args...)> {<br>
+public:<br>
+  UniqueFunction() = default;<br>
+  UniqueFunction(std::nullptr_t) : UniqueFunction(){};<br>
+<br>
+  UniqueFunction(UniqueFunction const &) = delete;<br>
+  UniqueFunction &operator=(UniqueFunction const &) = delete;<br>
+<br>
+  UniqueFunction(UniqueFunction &&) noexcept = default;<br>
+  UniqueFunction &operator=(UniqueFunction &&) noexcept = default;<br>
+<br>
+  template <class Callable><br>
+  UniqueFunction(Callable &&Func)<br>
+      : CallablePtr(llvm::make_unique<<br>
+                    FunctionCallImpl<typename std::decay<Callable>::type>>(<br>
+            std::forward<Callable>(Func))) {}<br>
+<br>
+  operator bool() { return CallablePtr; }<br>
+<br>
+  Ret operator()(Args... As) {<br>
+    assert(CallablePtr);<br>
+    CallablePtr->Call(std::forward<wbr><Args>(As)...);<br>
+  }<br>
+<br>
+private:<br>
+  class FunctionCallBase {<br>
+  public:<br>
+    virtual ~FunctionCallBase() = default;<br>
+    virtual Ret Call(Args... As) = 0;<br>
+  };<br>
+<br>
+  template <class Callable><br>
+  class FunctionCallImpl final : public FunctionCallBase {<br>
+    static_assert(<br>
+        std::is_same<Callable, typename std::decay<Callable>::type>::v<wbr>alue,<br>
+        "FunctionCallImpl must be instanstiated with std::decay'ed types");<br>
+<br>
+  public:<br>
+    FunctionCallImpl(Callable Func) : Func(std::move(Func)) {}<br>
+<br>
+    Ret Call(Args... As) override { return Func(std::forward<Args>(As)...<wbr>); }<br>
+<br>
+  private:<br>
+    Callable Func;<br>
+  };<br>
+<br>
+  std::unique_ptr<FunctionCallBa<wbr>se> CallablePtr;<br>
+};<br>
+<br>
+/// Stores a callable object (Func) and arguments (Args) and allows to call the<br>
+/// callable with provided arguments later using `operator ()`. The arguments<br>
+/// are std::forward'ed into the callable in the body of `operator()`. Therefore<br>
+/// `operator()` can only be called once, as some of the arguments could be<br>
+/// std::move'ed into the callable on first call.<br>
+template <class Func, class... Args> struct ForwardBinder {<br>
+  using Tuple = std::tuple<typename std::decay<Func>::type,<br>
+                           typename std::decay<Args>::type...>;<br>
+  Tuple FuncWithArguments;<br>
+#ifndef NDEBUG<br>
+  bool WasCalled = false;<br>
+#endif<br>
+<br>
+public:<br>
+  ForwardBinder(Tuple FuncWithArguments)<br>
+      : FuncWithArguments(std::move(Fu<wbr>ncWithArguments)) {}<br>
+<br>
+private:<br>
+  template <std::size_t... Indexes, class... RestArgs><br>
+  auto CallImpl(llvm::integer_sequenc<wbr>e<std::size_t, Indexes...> Seq,<br>
+                RestArgs &&... Rest)<br>
+      -> decltype(std::get<0>(this->Fun<wbr>cWithArguments)(<br>
+          std::forward<Args>(std::get<In<wbr>dexes + 1>(this->FuncWithArguments))..<wbr>.,<br>
+          std::forward<RestArgs>(Rest)..<wbr>.)) {<br>
+    return std::get<0>(this->FuncWithArgu<wbr>ments)(<br>
+        std::forward<Args>(std::get<In<wbr>dexes + 1>(this->FuncWithArguments))..<wbr>.,<br>
+        std::forward<RestArgs>(Rest)..<wbr>.);<br>
+  }<br>
+<br>
+public:<br>
+  template <class... RestArgs><br>
+  auto operator()(RestArgs &&... Rest)<br>
+      -> decltype(CallImpl(llvm::index_<wbr>sequence_for<Args...>(),<br>
+                           std::forward<RestArgs>(Rest).<wbr>..)) {<br>
+<br>
+#ifndef NDEBUG<br>
+    assert(!WasCalled && "Can only call result of BindWithForward once.");<br>
+    WasCalled = true;<br>
+#endif<br>
+    return CallImpl(llvm::index_sequence_<wbr>for<Args...>(),<br>
+                    std::forward<RestArgs>(Rest)..<wbr>.);<br>
+  }<br>
+};<br>
+<br>
+/// Creates an object that stores a callable (\p F) and first arguments to the<br>
+/// callable (\p As) and allows to call \p F with \Args at a later point.<br>
+/// Similar to std::bind, but also works with move-only \p F and \p As.<br>
+///<br>
+/// The returned object must be called no more than once, as \p As are<br>
+/// std::forwarded'ed (therefore can be moved) into \p F during the call.<br>
+template <class Func, class... Args><br>
+ForwardBinder<Func, Args...> BindWithForward(Func F, Args &&... As) {<br>
+  return ForwardBinder<Func, Args...>(<br>
+      std::make_tuple(std::forward<F<wbr>unc>(F), std::forward<Args>(As)...));<br>
+}<br>
+<br>
+} // namespace clangd<br>
+} // namespace clang<br>
+<br>
+#endif<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</blockquote></div></div>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Regards,</div><div>Ilya Biryukov</div></div></div></div></div>
</div>