Commit 031ed38a authored by Hannes Roth's avatar Hannes Roth Committed by facebook-github-bot-4

(Wangle) within should raise TimedOut()

Summary: A timeout now raises `TimedOut()` on the current Future.

Reviewed By: @fugalh

Differential Revision: D2261559
parent d3928f05
......@@ -857,32 +857,36 @@ Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
struct Context {
Context(E ex) : exception(std::move(ex)), promise() {}
E exception;
Future<Unit> thisFuture;
Promise<T> promise;
std::atomic<bool> token {false};
};
auto ctx = std::make_shared<Context>(std::move(e));
if (!tk) {
tk = folly::detail::getTimekeeperSingleton();
}
tk->after(dur)
.then([ctx](Try<Unit> const& t) {
if (ctx->token.exchange(true) == false) {
if (t.hasException()) {
ctx->promise.setException(std::move(t.exception()));
} else {
ctx->promise.setException(std::move(ctx->exception));
}
}
});
auto ctx = std::make_shared<Context>(std::move(e));
this->then([ctx](Try<T>&& t) {
ctx->thisFuture = this->then([ctx](Try<T>&& t) mutable {
// TODO: "this" completed first, cancel "after"
if (ctx->token.exchange(true) == false) {
ctx->promise.setTry(std::move(t));
}
});
tk->after(dur).then([ctx](Try<Unit> const& t) mutable {
// "after" completed first, cancel "this"
ctx->thisFuture.raise(TimedOut());
if (ctx->token.exchange(true) == false) {
if (t.hasException()) {
ctx->promise.setException(std::move(t.exception()));
} else {
ctx->promise.setException(std::move(ctx->exception));
}
}
});
return ctx->promise.getFuture().via(getExecutor());
}
......
......@@ -18,6 +18,7 @@
#include <folly/futures/Future.h>
#include <folly/futures/Promise.h>
#include <folly/Baton.h>
using namespace folly;
......@@ -72,3 +73,13 @@ TEST(Interrupt, secondInterruptNoop) {
f.cancel();
EXPECT_EQ(1, count);
}
TEST(Interrupt, withinTimedOut) {
Promise<int> p;
Baton<> done;
p.setInterruptHandler([&](const exception_wrapper& e) { done.post(); });
p.getFuture().within(std::chrono::milliseconds(1));
// Give it 100ms to time out and call the interrupt handler
auto t = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
EXPECT_TRUE(done.timed_wait(t));
}
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