(Wangle) within should raise TimedOut()
authorHannes Roth <hannesr@fb.com>
Tue, 21 Jul 2015 02:42:45 +0000 (19:42 -0700)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Tue, 21 Jul 2015 23:52:47 +0000 (16:52 -0700)
Summary: A timeout now raises `TimedOut()` on the current Future.

Reviewed By: @fugalh

Differential Revision: D2261559

folly/futures/Future-inl.h
folly/futures/test/InterruptTest.cpp

index 380b006925fcd97647cde9e0cac4565be729d2a6..0756fd34423f6e5a8e54ab1f3f978f4bb33884b4 100644 (file)
@@ -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());
 }
 
index 99f8b696bb91d6c863583465bd72a12277ecd46d..65f169edac434f8f8903492c4bfe18c9a2d19960 100644 (file)
@@ -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));
+}