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,11 +35,13 @@ Task<semi_await_result_t<Awaitable>> detachOnCancel(Awaitable awaitable) { ...@@ -35,11 +35,13 @@ 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( {
auto t = co_invoke(
[awaitable = std::move( [awaitable = std::move(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> { awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
co_return co_await std::move(awaitable); co_return co_await std::move(awaitable);
}) });
std::move(t)
.scheduleOn(co_await co_current_executor) .scheduleOn(co_await co_current_executor)
.startInlineUnsafe( .startInlineUnsafe(
[postedPtr = posted.get(), &baton, &result](auto&& r) { [postedPtr = posted.get(), &baton, &result](auto&& r) {
...@@ -51,6 +53,8 @@ Task<semi_await_result_t<Awaitable>> detachOnCancel(Awaitable awaitable) { ...@@ -51,6 +53,8 @@ Task<semi_await_result_t<Awaitable>> detachOnCancel(Awaitable awaitable) {
} }
}, },
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);
std::move(sleepFuture)
.setCallback_([posted, &baton, executor = co_await co_current_executor](
auto&&, auto&&) { 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( {
auto t = co_invoke(
[awaitable = std::move( [awaitable = std::move(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> { awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
co_return co_await std::move(awaitable); co_return co_await std::move(awaitable);
}) });
std::move(t)
.scheduleOn(co_await co_current_executor) .scheduleOn(co_await co_current_executor)
.start([posted, &baton, &result](auto&& r) { .start([posted, &baton, &result](auto&& r) {
if (!posted->exchange(true, std::memory_order_relaxed)) { if (!posted->exchange(true, std::memory_order_relaxed)) {
result = std::move(r); result = std::move(r);
baton.post(); 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