Summary: A timeout now raises `TimedOut()` on the current Future.
Reviewed By: @fugalh
Differential Revision:
D2261559
struct Context {
Context(E ex) : exception(std::move(ex)), promise() {}
E exception;
struct Context {
Context(E ex) : exception(std::move(ex)), promise() {}
E exception;
+ Future<Unit> thisFuture;
Promise<T> promise;
std::atomic<bool> token {false};
};
Promise<T> promise;
std::atomic<bool> token {false};
};
- auto ctx = std::make_shared<Context>(std::move(e));
if (!tk) {
tk = folly::detail::getTimekeeperSingleton();
}
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));
}
});
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());
}
return ctx->promise.getFuture().via(getExecutor());
}
#include <folly/futures/Future.h>
#include <folly/futures/Promise.h>
#include <folly/futures/Future.h>
#include <folly/futures/Promise.h>
+#include <folly/Baton.h>
f.cancel();
EXPECT_EQ(1, count);
}
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));
+}