Future::ensure
authorHans Fugal <fugalh@fb.com>
Wed, 25 Feb 2015 17:54:53 +0000 (09:54 -0800)
committerAlecs King <int@fb.com>
Tue, 3 Mar 2015 03:29:47 +0000 (19:29 -0800)
Summary: Unconditionally execute the action, passthrough semantics.

Test Plan: new unit test

Reviewed By: bmatheny@fb.com

Subscribers: trunkagent, exa, folly-diffs@, yfeldblum, jsedgwick

FB internal diff: D1868837

Tasks: 6166860

Signature: t1:1868837:1424820181:0e83f54b59d7091dac60ab65feb387992e8ae89c

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

index c4eda6053fbeba27d2007b1d3e952b596625bc40..a7183180dbc9bc387a9ce19ec5b78e2120c5aa95 100644 (file)
@@ -290,6 +290,16 @@ Future<T>::onError(F&& func) {
   return f;
 }
 
+template <class T>
+template <class F>
+Future<T> Future<T>::ensure(F func) {
+  MoveWrapper<F> funcw(std::move(func));
+  return this->then([funcw](Try<T>&& t) {
+    (*funcw)();
+    return makeFuture(std::move(t));
+  });
+}
+
 template <class T>
 template <class F>
 Future<T> Future<T>::onTimeout(Duration dur, F&& func, Timekeeper* tk) {
index 3459a7ad4d988c1eeeb6f390c2034de856e4868e..a43755e19e13ef390d5ab86c1cbf7dddeb17c5a7 100644 (file)
@@ -342,6 +342,13 @@ class Future {
     Future<T>>::type
   onError(F&& func);
 
+  /// func is like std::function<void()> and is executed unconditionally, and
+  /// the value/exception is passed through to the resulting Future.
+  /// func shouldn't throw, but if it does it will be captured and propagated,
+  /// and discard any value/exception that this Future has obtained.
+  template <class F>
+  Future<T> ensure(F func);
+
   /// Like onError, but for timeouts. example:
   ///
   ///   Future<int> f = makeFuture<int>(42)
index fabde15f1033d89e1bb249d9020489c75136579e..19dd1fa8349df55a5927366c5f26b5cca94f86ac 100644 (file)
@@ -1317,3 +1317,15 @@ TEST(Future, via_then_get_was_racy) {
   ASSERT_TRUE(!!val);
   EXPECT_EQ(42, *val);
 }
+
+TEST(Future, ensure) {
+  size_t count = 0;
+  auto cob = [&]{ count++; };
+  auto f = makeFuture(42)
+    .ensure(cob)
+    .then([](int) { throw std::runtime_error("ensure"); })
+    .ensure(cob);
+
+  EXPECT_THROW(f.get(), std::runtime_error);
+  EXPECT_EQ(2, count);
+}