Make addTask[Remote]Future() work for functions returning void.
authorMartin Martin <mcm@fb.com>
Fri, 29 Apr 2016 18:54:34 +0000 (11:54 -0700)
committerFacebook Github Bot 2 <facebook-github-bot-2-bot@fb.com>
Fri, 29 Apr 2016 19:05:32 +0000 (12:05 -0700)
Summary:
There's no Future<void>, you're supposed to use Future<Unit>
instead.  Unit has a "Lift" template to do the conversion.

Reviewed By: andriigrynenko

Differential Revision: D3241498

fb-gh-sync-id: db12d4f343685bc613b701e023c860c2c903ed4c
fbshipit-source-id: db12d4f343685bc613b701e023c860c2c903ed4c

folly/experimental/fibers/FiberManager-inl.h
folly/experimental/fibers/FiberManager.h
folly/experimental/fibers/test/FibersTest.cpp

index 6bad3618b0da9dcb00a54dcc7b3d5c807cc31e5c..8f31ede10d53348f6c50eef18d30bc9b2f3c75b8 100644 (file)
@@ -281,9 +281,10 @@ void FiberManager::addTask(F&& func) {
 }
 
 template <typename F>
-auto FiberManager::addTaskFuture(F&& func)
-    -> folly::Future<typename std::result_of<F()>::type> {
-  using T = typename std::result_of<F()>::type;
+auto FiberManager::addTaskFuture(F&& func) -> folly::Future<
+    typename folly::Unit::Lift<typename std::result_of<F()>::type>::type> {
+  using T =
+      typename folly::Unit::Lift<typename std::result_of<F()>::type>::type;
   folly::Promise<T> p;
   auto f = p.getFuture();
   addTaskFinally(
@@ -312,9 +313,11 @@ void FiberManager::addTaskRemote(F&& func) {
 }
 
 template <typename F>
-auto FiberManager::addTaskRemoteFuture(F&& func)
-    -> folly::Future<typename std::result_of<F()>::type> {
-  folly::Promise<typename std::result_of<F()>::type> p;
+auto FiberManager::addTaskRemoteFuture(F&& func) -> folly::Future<
+    typename folly::Unit::Lift<typename std::result_of<F()>::type>::type> {
+  folly::Promise<
+      typename folly::Unit::Lift<typename std::result_of<F()>::type>::type>
+      p;
   auto f = p.getFuture();
   addTaskRemote(
       [ p = std::move(p), func = std::forward<F>(func), this ]() mutable {
@@ -395,7 +398,8 @@ struct FiberManager::AddTaskFinallyHelper {
 
 template <typename F, typename G>
 void FiberManager::addTaskFinally(F&& func, G&& finally) {
-  typedef typename std::result_of<F()>::type Result;
+  typedef typename folly::Unit::Lift<typename std::result_of<F()>::type>::type
+      Result;
 
   static_assert(
       IsRvalueRefTry<typename FirstArgOf<G>::type>::value,
index 73a243ce884928eb58968c0ddfad1e7f44920d32..559f70e79f799bcc1e21e2cc60169718e8ed75dd 100644 (file)
@@ -190,8 +190,8 @@ class FiberManager : public ::folly::Executor {
    *             The object will be destroyed once task execution is complete.
    */
   template <typename F>
-  auto addTaskFuture(F&& func)
-      -> folly::Future<typename std::result_of<F()>::type>;
+  auto addTaskFuture(F&& func) -> folly::Future<
+      typename folly::Unit::Lift<typename std::result_of<F()>::type>::type>;
   /**
    * Add a new task to be executed. Safe to call from other threads.
    *
@@ -209,8 +209,8 @@ class FiberManager : public ::folly::Executor {
    *             The object will be destroyed once task execution is complete.
    */
   template <typename F>
-  auto addTaskRemoteFuture(F&& func)
-      -> folly::Future<typename std::result_of<F()>::type>;
+  auto addTaskRemoteFuture(F&& func) -> folly::Future<
+      typename folly::Unit::Lift<typename std::result_of<F()>::type>::type>;
 
   // Executor interface calls addTaskRemote
   void add(folly::Func f) override {
index ac66df6e748e5cf2974bb4588ff09b9c1fe5e062..08d182ff2890df8775e06cca992e9affcaaf0fc0 100644 (file)
@@ -1406,6 +1406,29 @@ TEST(FiberManager, remoteFutureTest) {
   EXPECT_EQ(v2, testValue2);
 }
 
+// Test that a void function produes a Future<Unit>.
+TEST(FiberManager, remoteFutureVoidUnitTest) {
+  FiberManager fiberManager(folly::make_unique<SimpleLoopController>());
+  auto& loopController =
+      dynamic_cast<SimpleLoopController&>(fiberManager.loopController());
+
+  bool ranLocal = false;
+  folly::Future<folly::Unit> futureLocal =
+      fiberManager.addTaskFuture([&]() { ranLocal = true; });
+
+  bool ranRemote = false;
+  folly::Future<folly::Unit> futureRemote =
+      fiberManager.addTaskRemoteFuture([&]() { ranRemote = true; });
+
+  loopController.loop([&]() { loopController.stop(); });
+
+  futureLocal.wait();
+  ASSERT_TRUE(ranLocal);
+
+  futureRemote.wait();
+  ASSERT_TRUE(ranRemote);
+}
+
 TEST(FiberManager, nestedFiberManagers) {
   folly::EventBase outerEvb;
   folly::EventBase innerEvb;