From 031ed38a57114bca7a72dd61a29ad84feaab60ed Mon Sep 17 00:00:00 2001 From: Hannes Roth Date: Mon, 20 Jul 2015 19:42:45 -0700 Subject: [PATCH] (Wangle) within should raise TimedOut() Summary: A timeout now raises `TimedOut()` on the current Future. Reviewed By: @fugalh Differential Revision: D2261559 --- folly/futures/Future-inl.h | 28 ++++++++++++++++------------ folly/futures/test/InterruptTest.cpp | 11 +++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h index 380b0069..0756fd34 100644 --- a/folly/futures/Future-inl.h +++ b/folly/futures/Future-inl.h @@ -857,32 +857,36 @@ Future Future::within(Duration dur, E e, Timekeeper* tk) { struct Context { Context(E ex) : exception(std::move(ex)), promise() {} E exception; + Future thisFuture; Promise promise; std::atomic token {false}; }; - auto ctx = std::make_shared(std::move(e)); if (!tk) { tk = folly::detail::getTimekeeperSingleton(); } - tk->after(dur) - .then([ctx](Try 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(std::move(e)); - this->then([ctx](Try&& t) { + ctx->thisFuture = this->then([ctx](Try&& 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 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()); } diff --git a/folly/futures/test/InterruptTest.cpp b/folly/futures/test/InterruptTest.cpp index 99f8b696..65f169ed 100644 --- a/folly/futures/test/InterruptTest.cpp +++ b/folly/futures/test/InterruptTest.cpp @@ -18,6 +18,7 @@ #include #include +#include using namespace folly; @@ -72,3 +73,13 @@ TEST(Interrupt, secondInterruptNoop) { f.cancel(); EXPECT_EQ(1, count); } + +TEST(Interrupt, withinTimedOut) { + Promise 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)); +} -- 2.34.1