Unify runInMainContext for void and non-void
authorAndrii Grynenko <andrii@fb.com>
Mon, 15 Feb 2016 19:32:24 +0000 (11:32 -0800)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Mon, 15 Feb 2016 20:20:26 +0000 (12:20 -0800)
Summary: This also fixes a bug where exception was not re-thrown for functions returning void.

Reviewed By: spalamarchuk

Differential Revision: D2936887

fb-gh-sync-id: 9828dec131203528c27eae874aba147168f40d0d
shipit-source-id: 9828dec131203528c27eae874aba147168f40d0d

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

index 8c22010b7770ad97062e1e7b76bf743eb34910c6..b0a6334e457d56a268073fafaefc0eec915a91f1 100644 (file)
@@ -429,14 +429,6 @@ void FiberManager::addTaskFinally(F&& func, G&& finally) {
 template <typename F>
 typename std::result_of<F()>::type
 FiberManager::runInMainContext(F&& func) {
-  return runInMainContextHelper(std::forward<F>(func));
-}
-
-template <typename F>
-inline typename std::enable_if<
-  !std::is_same<typename std::result_of<F()>::type, void>::value,
-  typename std::result_of<F()>::type>::type
-FiberManager::runInMainContextHelper(F&& func) {
   if (UNLIKELY(activeFiber_ == nullptr)) {
     return func();
   }
@@ -451,21 +443,7 @@ FiberManager::runInMainContextHelper(F&& func) {
   immediateFunc_ = std::ref(f);
   activeFiber_->preempt(Fiber::AWAITING_IMMEDIATE);
 
-  return std::move(result.value());
-}
-
-template <typename F>
-inline typename std::enable_if<
-  std::is_same<typename std::result_of<F()>::type, void>::value,
-  void>::type
-FiberManager::runInMainContextHelper(F&& func) {
-  if (UNLIKELY(activeFiber_ == nullptr)) {
-    func();
-    return;
-  }
-
-  immediateFunc_ = std::ref(func);
-  activeFiber_->preempt(Fiber::AWAITING_IMMEDIATE);
+  return std::move(result).value();
 }
 
 inline FiberManager& FiberManager::getFiberManager() {
index 92d9cef346280823d1db3230b0174f4e975bae73..f90b9d67444a8591c11dc8f1dcd8b3ea57a52d38 100644 (file)
@@ -373,24 +373,6 @@ class FiberManager : public ::folly::Executor {
    */
   static FOLLY_TLS FiberManager* currentFiberManager_;
 
-  /**
-   * runInMainContext implementation for non-void functions.
-   */
-  template <typename F>
-  typename std::enable_if<
-    !std::is_same<typename std::result_of<F()>::type, void>::value,
-    typename std::result_of<F()>::type>::type
-  runInMainContextHelper(F&& func);
-
-  /**
-   * runInMainContext implementation for void functions
-   */
-  template <typename F>
-  typename std::enable_if<
-    std::is_same<typename std::result_of<F()>::type, void>::value,
-    void>::type
-  runInMainContextHelper(F&& func);
-
   /**
    * Allocator used to allocate stack for Fibers in the pool.
    * Allocates stack on the stack of the main context.
index e3eb2f740408a5e47270f6a1958ea8395d273858..b7c69c9cd43237839723e751f44693fdc6c13164 100644 (file)
@@ -937,16 +937,22 @@ TEST(FiberManager, runInMainContext) {
 
   checkRan = false;
 
-  manager.addTask(
-    [&]() {
-      int stackLocation;
-      runInMainContext(
-        [&]() {
-          expectMainContext(checkRan, &mainLocation, &stackLocation);
-        });
-      EXPECT_TRUE(checkRan);
-    }
-  );
+  manager.addTask([&]() {
+    struct A {
+      explicit A(int value_) : value(value_) {}
+      A(const A&) = delete;
+      A(A&&) = default;
+
+      int value;
+    };
+    int stackLocation;
+    auto ret = runInMainContext([&]() {
+      expectMainContext(checkRan, &mainLocation, &stackLocation);
+      return A(42);
+    });
+    EXPECT_TRUE(checkRan);
+    EXPECT_EQ(42, ret.value);
+  });
 
   loopController.loop(
     [&]() {
index 1d0d1d27e9a460306aef748bed7421473eeb2c1b..499dfa446e3b068b63c46565b33d3fd2705dccaa 100644 (file)
@@ -102,13 +102,19 @@ Try<T>::~Try() {
 }
 
 template <class T>
-T& Try<T>::value() {
+T& Try<T>::value() {
   throwIfFailed();
   return value_;
 }
 
 template <class T>
-const T& Try<T>::value() const {
+T&& Try<T>::value() && {
+  throwIfFailed();
+  return std::move(value_);
+}
+
+template <class T>
+const T& Try<T>::value() const & {
   throwIfFailed();
   return value_;
 }
index 437127b8c67802fd051e7db29fa64f609b128479..b4152dd46c2c796559f62d42c19e034d73c8feaf 100644 (file)
@@ -124,14 +124,21 @@ class Try {
    *
    * @returns mutable reference to the contained value
    */
-  T& value();
+  T& value()&;
+  /*
+   * Get a rvalue reference to the contained value. If the Try contains an
+   * exception it will be rethrown.
+   *
+   * @returns rvalue reference to the contained value
+   */
+  T&& value()&&;
   /*
    * Get a const reference to the contained value. If the Try contains an
    * exception it will be rethrown.
    *
    * @returns const reference to the contained value
    */
-  const T& value() const;
+  const T& value() const&;
 
   /*
    * If the Try contains an exception, rethrow it. Otherwise do nothing.