Commit 10dd9f4b authored by Pranav Thulasiram Bhat's avatar Pranav Thulasiram Bhat Committed by Facebook GitHub Bot

Switch await into a callable object

Summary: This diff converts `await` into a callable object.

Reviewed By: yfeldblum

Differential Revision: D22175597

fbshipit-source-id: 689e11c62161a2e4b82699bf52835e92c96beff7
parent b18832a6
...@@ -24,19 +24,23 @@ namespace folly { ...@@ -24,19 +24,23 @@ namespace folly {
namespace fibers { namespace fibers {
namespace async { namespace async {
template <typename T>
class Async;
namespace detail { namespace detail {
/** /**
* Define in source to avoid including FiberManager header and keep this file * Define in source to avoid including FiberManager header and keep this file
* cheap to include * cheap to include
*/ */
bool onFiber(); bool onFiber();
} // namespace detail
template <typename T> struct await_fn {
class Async; template <typename T>
T&& operator()(Async<T>&&) const noexcept;
template <typename T> void operator()(Async<void>&&) const noexcept {}
T&& await(Async<T>&&); };
} // namespace detail
/** /**
* Asynchronous fiber result wrapper * Asynchronous fiber result wrapper
...@@ -75,7 +79,7 @@ class [[nodiscard]] Async { ...@@ -75,7 +79,7 @@ class [[nodiscard]] Async {
// Move constructor to allow eager-return of async without using await // Move constructor to allow eager-return of async without using await
template <typename U> template <typename U>
/* implicit */ Async(Async<U> && async) noexcept /* implicit */ Async(Async<U> && async) noexcept
: val_(await(std::move(async))) {} : val_(static_cast<U&&>(async.val_)) {}
Async(const Async&) = delete; Async(const Async&) = delete;
Async(Async && other) = default; Async(Async && other) = default;
...@@ -84,7 +88,11 @@ class [[nodiscard]] Async { ...@@ -84,7 +88,11 @@ class [[nodiscard]] Async {
private: private:
T val_; T val_;
friend T&& await<T>(Async<T> &&);
template <typename U>
friend class Async;
friend struct detail::await_fn;
}; };
template <> template <>
...@@ -108,21 +116,20 @@ template <typename T> ...@@ -108,21 +116,20 @@ template <typename T>
explicit Async(T)->Async<T>; explicit Async(T)->Async<T>;
#endif #endif
namespace detail {
template <typename T>
T&& await_fn::operator()(Async<T>&& async) const noexcept {
return static_cast<T&&>(async.val_);
}
} // namespace detail
/** /**
* Function to retrieve the result from the Async wrapper * Function to retrieve the result from the Async wrapper
* A function calling await must return an Async wrapper itself * A function calling await must return an Async wrapper itself
* for the wrapper to serve its intended purpose (the best way to enforce this * for the wrapper to serve its intended purpose (the best way to enforce this
* is static analysis) * is static analysis)
*/ */
template <typename T> constexpr detail::await_fn await;
T&& await(Async<T>&& async) {
DCHECK(detail::onFiber());
return static_cast<T&&>(async.val_);
}
inline void await(Async<void>&&) {
DCHECK(detail::onFiber());
}
/** /**
* A utility to start annotating at top of stack (eg. the task which is added to * A utility to start annotating at top of stack (eg. the task which is added to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment