Commit c01f0afd authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Use dummy KeepAlive for nested Tasks

Reviewed By: lewissbaker

Differential Revision: D13658986

fbshipit-source-id: af03f4e2edea93371fc37773f2fea152f7c589f8
parent 5c8439f9
...@@ -114,6 +114,13 @@ class Executor { ...@@ -114,6 +114,13 @@ class Executor {
return getKeepAliveToken(get()); return getKeepAliveToken(get());
} }
// Creates a dummy copy of this KeepAlive token, which doesn't increment
// the ref-count. Should only be used if this KeepAlive token is known to
// outlive such dummy copy.
KeepAlive copyDummy() const {
return KeepAlive(get(), true);
}
private: private:
static constexpr intptr_t kDummyFlag = 1; static constexpr intptr_t kDummyFlag = 1;
static constexpr intptr_t kExecutorMask = ~kDummyFlag; static constexpr intptr_t kExecutorMask = ~kDummyFlag;
......
...@@ -404,7 +404,7 @@ auto detail::TaskPromiseBase::await_transform(Task<T>&& t) noexcept { ...@@ -404,7 +404,7 @@ auto detail::TaskPromiseBase::await_transform(Task<T>&& t) noexcept {
}; };
// Child task inherits the awaiting task's executor // Child task inherits the awaiting task's executor
t.coro_.promise().executor_ = executor_.copy(); t.coro_.promise().executor_ = executor_.copyDummy();
return Awaiter{std::exchange(t.coro_, {})}; return Awaiter{std::exchange(t.coro_, {})};
} }
......
...@@ -128,6 +128,40 @@ TEST(Coro, ExecutorKeepAlive) { ...@@ -128,6 +128,40 @@ TEST(Coro, ExecutorKeepAlive) {
EXPECT_TRUE(future.isReady()); EXPECT_TRUE(future.isReady());
} }
struct CountingExecutor : public ManualExecutor {
bool keepAliveAcquire() override {
++keepAliveCounter;
return true;
}
void keepAliveRelease() override {
--keepAliveCounter;
}
size_t keepAliveCounter{0};
};
coro::Task<void> executorRec(int depth) {
if (depth == 0) {
co_return;
}
auto executor =
dynamic_cast<CountingExecutor*>(co_await coro::co_current_executor);
DCHECK(executor);
// Note, extra keep-alives are being kept by the Futures.
EXPECT_EQ(3, executor->keepAliveCounter);
co_await executorRec(depth - 1);
}
TEST(Coro, ExecutorKeepAliveDummy) {
CountingExecutor executor;
executorRec(42).scheduleOn(&executor).start().via(&executor).getVia(
&executor);
}
coro::Task<int> taskException() { coro::Task<int> taskException() {
throw std::runtime_error("Test exception"); throw std::runtime_error("Test exception");
co_return 42; co_return 42;
......
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