From: Hans Fugal <fugalh@fb.com>
Date: Mon, 30 Mar 2015 15:44:48 +0000 (-0700)
Subject: Future::filter(A => bool)
X-Git-Tag: v0.33.0~20
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=77c9cc673969bb90e92b13b505d38164249dd024;p=folly.git

Future::filter(A => bool)

Test Plan: new unit tests

Reviewed By: davejwatson@fb.com

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

FB internal diff: D1828251

Tasks: 6166893

Signature: t1:1828251:1427475565:512463d5728482a40c1da2548a5bed91e7f92d60
---

diff --git a/folly/futures/Future-inl.h b/folly/futures/Future-inl.h
index 9d37c165..dc842741 100644
--- a/folly/futures/Future-inl.h
+++ b/folly/futures/Future-inl.h
@@ -825,6 +825,19 @@ Future<bool> Future<T>::willEqual(Future<T>& f) {
   });
 }
 
+template <class T>
+template <class F>
+Future<T> Future<T>::filter(F predicate) {
+  auto p = folly::makeMoveWrapper(std::move(predicate));
+  return this->then([p](T val) {
+    T const& valConstRef = val;
+    if (!(*p)(valConstRef)) {
+      throw PredicateDoesNotObtain();
+    }
+    return val;
+  });
+}
+
 namespace futures {
   namespace {
     template <class Z>
diff --git a/folly/futures/Future.h b/folly/futures/Future.h
index 3d4dff2c..f507748d 100644
--- a/folly/futures/Future.h
+++ b/folly/futures/Future.h
@@ -474,6 +474,12 @@ class Future {
   /// exception)
   Future<bool> willEqual(Future<T>&);
 
+  /// predicate behaves like std::function<bool(T const&)>
+  /// If the predicate does not obtain with the value, the result
+  /// is a folly::PredicateDoesNotObtain exception
+  template <class F>
+  Future<T> filter(F predicate);
+
  protected:
   typedef detail::Core<T>* corePtr;
 
diff --git a/folly/futures/FutureException.h b/folly/futures/FutureException.h
index dce9e262..1e004dcf 100644
--- a/folly/futures/FutureException.h
+++ b/folly/futures/FutureException.h
@@ -91,4 +91,9 @@ class TimedOut : public FutureException {
   TimedOut() : FutureException("Timed out") {}
 };
 
+class PredicateDoesNotObtain : public FutureException {
+ public:
+  PredicateDoesNotObtain() : FutureException("Predicate does not obtain") {}
+};
+
 }
diff --git a/folly/futures/test/SugarTest.cpp b/folly/futures/test/SugarTest.cpp
index 152fe546..bbafdebb 100644
--- a/folly/futures/test/SugarTest.cpp
+++ b/folly/futures/test/SugarTest.cpp
@@ -27,15 +27,31 @@ TEST(Sugar, pollReady) {
   EXPECT_EQ(42, f.poll().value().value());
 }
 
-TEST(SUGAR, pollNotReady) {
+TEST(Sugar, pollNotReady) {
   Promise<int> p;
   auto f = p.getFuture();
   EXPECT_FALSE(f.poll().hasValue());
 }
 
-TEST(SUGAR, pollException) {
+TEST(Sugar, pollException) {
   Promise<void> p;
   auto f = p.getFuture();
   p.fulfil([] { throw std::runtime_error("Runtime"); });
   EXPECT_TRUE(f.poll().value().hasException());
 }
+
+TEST(Sugar, filterTrue) {
+  EXPECT_EQ(42, makeFuture(42).filter([](int){ return true; }).get());
+}
+
+TEST(Sugar, filterFalse) {
+  EXPECT_THROW(makeFuture(42).filter([](int){ return false; }).get(),
+               folly::PredicateDoesNotObtain);
+}
+
+TEST(Sugar, filterMoveonly) {
+  EXPECT_EQ(42,
+    *makeFuture(folly::make_unique<int>(42))
+     .filter([](std::unique_ptr<int> const&) { return true; })
+     .get());
+}