Commit 4720e456 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook GitHub Bot

GCC compiler bug workaround for timed_wait and detachOnCancel

Summary: GCC seems to be generating incorrect code for some mix of co_invoke and start/startInline. This workaround makes coro tests pass.

Reviewed By: yfeldblum

Differential Revision: D28174118

fbshipit-source-id: b8178d7711ed5619a37c169f8f18dd125bf08f0b
parent 9454bc45
...@@ -35,22 +35,26 @@ Task<semi_await_result_t<Awaitable>> detachOnCancel(Awaitable awaitable) { ...@@ -35,22 +35,26 @@ Task<semi_await_result_t<Awaitable>> detachOnCancel(Awaitable awaitable) {
Baton baton; Baton baton;
Try<detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>> result; Try<detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>> result;
co_invoke( {
[awaitable = std::move( auto t = co_invoke(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> { [awaitable = std::move(
co_return co_await std::move(awaitable); awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
}) co_return co_await std::move(awaitable);
.scheduleOn(co_await co_current_executor) });
.startInlineUnsafe( std::move(t)
[postedPtr = posted.get(), &baton, &result](auto&& r) { .scheduleOn(co_await co_current_executor)
std::unique_ptr<std::atomic<bool>> p(postedPtr); .startInlineUnsafe(
if (!p->exchange(true, std::memory_order_relaxed)) { [postedPtr = posted.get(), &baton, &result](auto&& r) {
p.release(); std::unique_ptr<std::atomic<bool>> p(postedPtr);
tryAssign(result, std::move(r)); if (!p->exchange(true, std::memory_order_relaxed)) {
baton.post(); p.release();
} tryAssign(result, std::move(r));
}, baton.post();
co_await co_current_cancellation_token); }
},
co_await co_current_cancellation_token);
}
{ {
CancellationCallback cancelCallback( CancellationCallback cancelCallback(
co_await co_current_cancellation_token, [&posted, &baton, &result] { co_await co_current_cancellation_token, [&posted, &baton, &result] {
......
...@@ -35,32 +35,40 @@ template <typename Awaitable> ...@@ -35,32 +35,40 @@ template <typename Awaitable>
Task<Optional<lift_unit_t<detail::decay_rvalue_reference_t< Task<Optional<lift_unit_t<detail::decay_rvalue_reference_t<
detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>>>>> detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>>>>>
timed_wait(Awaitable awaitable, Duration duration) { timed_wait(Awaitable awaitable, Duration duration) {
auto posted = std::make_shared<std::atomic<bool>>(false);
Baton baton; Baton baton;
Try<lift_unit_t<detail::decay_rvalue_reference_t< Try<lift_unit_t<detail::decay_rvalue_reference_t<
detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>>>> detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>>>>
result; result;
futures::sleep(duration).toUnsafeFuture().setCallback_( auto sleepFuture = futures::sleep(duration).toUnsafeFuture();
[posted, &baton, executor = co_await co_current_executor]( auto posted = new std::atomic<bool>(false);
auto&&, auto&&) { std::move(sleepFuture)
.setCallback_([posted, &baton, executor = co_await co_current_executor](
auto&&, auto&&) {
if (!posted->exchange(true, std::memory_order_relaxed)) { if (!posted->exchange(true, std::memory_order_relaxed)) {
executor->add([&baton] { baton.post(); }); executor->add([&baton] { baton.post(); });
} else {
delete posted;
} }
}); });
co_invoke( {
[awaitable = std::move( auto t = co_invoke(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> { [awaitable = std::move(
co_return co_await std::move(awaitable); awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
}) co_return co_await std::move(awaitable);
.scheduleOn(co_await co_current_executor) });
.start([posted, &baton, &result](auto&& r) { std::move(t)
if (!posted->exchange(true, std::memory_order_relaxed)) { .scheduleOn(co_await co_current_executor)
result = std::move(r); .start([posted, &baton, &result](auto&& r) {
baton.post(); if (!posted->exchange(true, std::memory_order_relaxed)) {
} result = std::move(r);
}); baton.post();
} else {
delete posted;
}
});
}
co_await detail::UnsafeResumeInlineSemiAwaitable{get_awaiter(baton)}; co_await detail::UnsafeResumeInlineSemiAwaitable{get_awaiter(baton)};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment