<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">http://lab.llvm.org:8011/builders/clang-x86_64-linux-abi-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-<wbr>project?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/<wbr>D38627</a><br>
<br>
Added:<br>
clang-tools-extra/trunk/<wbr>clangd/Function.h<br>
Modified:<br>
clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp<br>
clang-tools-extra/trunk/<wbr>clangd/ClangdServer.h<br>
<br>
Modified: clang-tools-extra/trunk/<wbr>clangd/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-<wbr>project/clang-tools-extra/<wbr>trunk/clangd/ClangdServer.cpp?<wbr>rev=315210&r1=315209&r2=<wbr>315210&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp (original)<br>
+++ clang-tools-extra/trunk/<wbr>clangd/ClangdServer.cpp Mon Oct 9 09:26:26 2017<br>
@@ -99,7 +99,7 @@ ClangdScheduler::<wbr>ClangdScheduler(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::<wbr>ClangdScheduler(unsigne<br>
RequestQueue.pop_front();<br>
} // unlock Mutex<br>
<br>
- Request.get();<br>
+ Request();<br>
}<br>
}));<br>
}<br>
<br>
Modified: clang-tools-extra/trunk/<wbr>clangd/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-<wbr>project/clang-tools-extra/<wbr>trunk/clangd/ClangdServer.h?<wbr>rev=315210&r1=315209&r2=<wbr>315210&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/<wbr>clangd/ClangdServer.h (original)<br>
+++ clang-tools-extra/trunk/<wbr>clangd/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::<wbr>async(std::launch::deferred,<br>
- std::forward<Func>(F),<br>
- std::forward<Args>(As)...));<br>
+ RequestQueue.push_front(<br>
+ BindWithForward(std::forward<<wbr>Func>(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::<wbr>async(std::launch::deferred,<br>
- std::forward<Func>(F),<br>
- std::forward<Args>(As)...));<br>
+ RequestQueue.push_back(<br>
+ BindWithForward(std::forward<<wbr>Func>(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::<wbr>deferred, ...)).<br>
- std::deque<std::future<void>> RequestQueue;<br>
+ std::deque<UniqueFunction<<wbr>void()>> RequestQueue;<br>
/// Condition variable to wake up worker threads.<br>
std::condition_variable RequestCV;<br>
};<br>
<br>
Added: clang-tools-extra/trunk/<wbr>clangd/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-<wbr>project/clang-tools-extra/<wbr>trunk/clangd/Function.h?rev=<wbr>315210&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- clang-tools-extra/trunk/<wbr>clangd/Function.h (added)<br>
+++ clang-tools-extra/trunk/<wbr>clangd/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::<wbr>forward<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>::<wbr>value,<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<<wbr>FunctionCallBase> 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(<wbr>FuncWithArguments)) {}<br>
+<br>
+private:<br>
+ template <std::size_t... Indexes, class... RestArgs><br>
+ auto CallImpl(llvm::integer_<wbr>sequence<std::size_t, Indexes...> Seq,<br>
+ RestArgs &&... Rest)<br>
+ -> decltype(std::get<0>(this-><wbr>FuncWithArguments)(<br>
+ std::forward<Args>(std::get<<wbr>Indexes + 1>(this->FuncWithArguments))..<wbr>.,<br>
+ std::forward<RestArgs>(Rest)..<wbr>.)) {<br>
+ return std::get<0>(this-><wbr>FuncWithArguments)(<br>
+ std::forward<Args>(std::get<<wbr>Indexes + 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<<wbr>Func>(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">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>