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) {
Baton baton;
Try<detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>> result;
co_invoke(
[awaitable = std::move(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
co_return co_await std::move(awaitable);
})
.scheduleOn(co_await co_current_executor)
.startInlineUnsafe(
[postedPtr = posted.get(), &baton, &result](auto&& r) {
std::unique_ptr<std::atomic<bool>> p(postedPtr);
if (!p->exchange(true, std::memory_order_relaxed)) {
p.release();
tryAssign(result, std::move(r));
baton.post();
}
},
co_await co_current_cancellation_token);
{
auto t = co_invoke(
[awaitable = std::move(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
co_return co_await std::move(awaitable);
});
std::move(t)
.scheduleOn(co_await co_current_executor)
.startInlineUnsafe(
[postedPtr = posted.get(), &baton, &result](auto&& r) {
std::unique_ptr<std::atomic<bool>> p(postedPtr);
if (!p->exchange(true, std::memory_order_relaxed)) {
p.release();
tryAssign(result, std::move(r));
baton.post();
}
},
co_await co_current_cancellation_token);
}
{
CancellationCallback cancelCallback(
co_await co_current_cancellation_token, [&posted, &baton, &result] {
......
......@@ -35,32 +35,40 @@ template <typename Awaitable>
Task<Optional<lift_unit_t<detail::decay_rvalue_reference_t<
detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>>>>>
timed_wait(Awaitable awaitable, Duration duration) {
auto posted = std::make_shared<std::atomic<bool>>(false);
Baton baton;
Try<lift_unit_t<detail::decay_rvalue_reference_t<
detail::lift_lvalue_reference_t<semi_await_result_t<Awaitable>>>>>
result;
futures::sleep(duration).toUnsafeFuture().setCallback_(
[posted, &baton, executor = co_await co_current_executor](
auto&&, auto&&) {
auto sleepFuture = futures::sleep(duration).toUnsafeFuture();
auto posted = new std::atomic<bool>(false);
std::move(sleepFuture)
.setCallback_([posted, &baton, executor = co_await co_current_executor](
auto&&, auto&&) {
if (!posted->exchange(true, std::memory_order_relaxed)) {
executor->add([&baton] { baton.post(); });
} else {
delete posted;
}
});
co_invoke(
[awaitable = std::move(
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) {
if (!posted->exchange(true, std::memory_order_relaxed)) {
result = std::move(r);
baton.post();
}
});
{
auto t = co_invoke(
[awaitable = std::move(
awaitable)]() mutable -> Task<semi_await_result_t<Awaitable>> {
co_return co_await std::move(awaitable);
});
std::move(t)
.scheduleOn(co_await co_current_executor)
.start([posted, &baton, &result](auto&& r) {
if (!posted->exchange(true, std::memory_order_relaxed)) {
result = std::move(r);
baton.post();
} else {
delete posted;
}
});
}
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