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

Fix SemiFuture::within to support deferred work

Reviewed By: yfeldblum

Differential Revision: D14109224

fbshipit-source-id: 4bcd40b8692478540f5b5b4ee2751f1d311b3ac5
parent 1b5288e6
......@@ -789,8 +789,18 @@ class SemiFuture : private futures::detail::FutureBase<T> {
template <class E>
SemiFuture<T> within(Duration dur, E e, Timekeeper* tk = nullptr) && {
return this->isReady() ? std::move(*this)
: std::move(*this).withinImplementation(dur, e, tk);
if (this->isReady()) {
return std::move(*this);
}
auto deferredExecutor = stealDeferredExecutor();
auto ret = std::move(*this).withinImplementation(dur, e, tk);
if (deferredExecutor) {
ret =
std::move(ret).defer([](Try<T>&& t) { return std::move(t).value(); });
ret.getDeferredExecutor()->setNestedExecutors(
{std::move(deferredExecutor)});
}
return ret;
}
/// Delay the completion of this SemiFuture for at least this duration from
......
......@@ -1077,3 +1077,25 @@ TEST(SemiFuture, DeferWithExecutor) {
[&](Executor* e, Try<Unit>) { EXPECT_EQ(&executor, e); });
std::move(sf).via(&executor).getVia(&executor);
}
TEST(SemiFuture, within) {
{
auto sf = makeSemiFuture(42)
.deferValue([](int x) { return x / 2; })
.within(std::chrono::seconds{10})
.deferValue([](int x) { return x * 2; });
EXPECT_EQ(42, std::move(sf).get());
}
{
folly::Promise<folly::Unit> p;
auto sf = p.getSemiFuture()
.deferValue([](auto) {
CHECK(false);
return -1;
})
.within(std::chrono::seconds{1})
.deferError(tag_t<FutureTimeout>{}, [](auto) { return 42; });
EXPECT_EQ(42, std::move(sf).get());
p.setValue();
}
}
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