Add willEqual to C++ Futures Code
authorMonica Lee <monicalee@fb.com>
Fri, 27 Feb 2015 17:37:25 +0000 (09:37 -0800)
committerAlecs King <int@fb.com>
Tue, 3 Mar 2015 03:30:37 +0000 (19:30 -0800)
Summary: Added willEqual function and wrote unit tests for it.

Test Plan: fbconfig --clang folly/futures && fbmake runtests

Reviewed By: hans@fb.com

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

FB internal diff: D1859840

Tasks: 6166911

Signature: t1:1859840:1424967149:865ee96ab4d3f5dbf17eb371b2ac3ccb5066ac87

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

index 78f3d86b144e13a89849e9c417b34ce3699c1bc6..6dd7a15514aca089c5244dd7d4af6f1395095732 100644 (file)
@@ -743,8 +743,18 @@ inline void Future<void>::getVia(DrivableExecutor* e) {
   waitVia(e).value();
 }
 
-namespace futures {
+template <class T>
+Future<bool> Future<T>::willEqual(Future<T>& f) {
+  return whenAll(*this, f).then([](const std::tuple<Try<T>, Try<T>>& t) {
+    if (std::get<0>(t).hasValue() && std::get<1>(t).hasValue()) {
+      return std::get<0>(t).value() == std::get<1>(t).value();
+    } else {
+      return false;
+      }
+  });
+}
 
+namespace futures {
   namespace {
     template <class Z>
     Future<Z> chainHelper(Future<Z> f) {
index 935fe15ad0ec8e8a37530c2a5d70edf8bf8f31a5..7021f4f20edace260fde27d502889746021e7541 100644 (file)
@@ -455,7 +455,12 @@ class Future {
   /// Overload of waitVia() for rvalue Futures
   Future<T>&& waitVia(DrivableExecutor* e) &&;
 
- protected:
+  /// If the value in this Future is equal to the given Future, when they have
+  /// both completed, the value of the resulting Future<bool> will be true. It
+  /// will be false otherwise (including when one or both Futures have an
+  /// exception)
+  Future<bool> willEqual(Future<T>&);
+
   typedef detail::Core<T>* corePtr;
 
   // shared core state object
index 48358e16470e7793c2854ceac9efb16ca73915c5..ed696f9a65c497313212bbb716f063a6a6358970 100644 (file)
@@ -1329,3 +1329,84 @@ TEST(Future, ensure) {
   EXPECT_THROW(f.get(), std::runtime_error);
   EXPECT_EQ(2, count);
 }
+
+TEST(Future, willEqual) {
+    //both p1 and p2 already fulfilled
+    {
+    Promise<int> p1;
+    Promise<int> p2;
+    p1.setValue(27);
+    p2.setValue(27);
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    EXPECT_TRUE(f1.willEqual(f2).get());
+    }{
+    Promise<int> p1;
+    Promise<int> p2;
+    p1.setValue(27);
+    p2.setValue(36);
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    EXPECT_FALSE(f1.willEqual(f2).get());
+    }
+    //both p1 and p2 not yet fulfilled
+    {
+    Promise<int> p1;
+    Promise<int> p2;
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    auto f3 = f1.willEqual(f2);
+    p1.setValue(27);
+    p2.setValue(27);
+    EXPECT_TRUE(f3.get());
+    }{
+    Promise<int> p1;
+    Promise<int> p2;
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    auto f3 = f1.willEqual(f2);
+    p1.setValue(27);
+    p2.setValue(36);
+    EXPECT_FALSE(f3.get());
+    }
+    //p1 already fulfilled, p2 not yet fulfilled
+    {
+    Promise<int> p1;
+    Promise<int> p2;
+    p1.setValue(27);
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    auto f3 = f1.willEqual(f2);
+    p2.setValue(27);
+    EXPECT_TRUE(f3.get());
+    }{
+    Promise<int> p1;
+    Promise<int> p2;
+    p1.setValue(27);
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    auto f3 = f1.willEqual(f2);
+    p2.setValue(36);
+    EXPECT_FALSE(f3.get());
+    }
+    //p2 already fulfilled, p1 not yet fulfilled
+    {
+    Promise<int> p1;
+    Promise<int> p2;
+    p2.setValue(27);
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    auto f3 = f1.willEqual(f2);
+    p1.setValue(27);
+    EXPECT_TRUE(f3.get());
+    }{
+    Promise<int> p1;
+    Promise<int> p2;
+    p2.setValue(36);
+    auto f1 = p1.getFuture();
+    auto f2 = p2.getFuture();
+    auto f3 = f1.willEqual(f2);
+    p1.setValue(27);
+    EXPECT_FALSE(f3.get());
+    }
+}