async_simple/coro/FutureAwaiter.h (48 lines of code) (raw):

/* * Copyright (c) 2022, Alibaba Group Holding Limited; * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ASYNC_SIMPLE_CORO_FUTURE_AWAITER_H #define ASYNC_SIMPLE_CORO_FUTURE_AWAITER_H #ifndef ASYNC_SIMPLE_USE_MODULES #include "async_simple/Future.h" #include "async_simple/coro/Lazy.h" #include "async_simple/experimental/coroutine.h" #include <type_traits> #endif // ASYNC_SIMPLE_USE_MODULES namespace async_simple { namespace coro::detail { template <typename T> struct FutureAwaiter { Future<T> future_; bool await_ready() { return future_.hasResult(); } template <typename PromiseType> void await_suspend(CoroHandle<PromiseType> continuation) { static_assert(std::is_base_of_v<LazyPromiseBase, PromiseType>, "FutureAwaiter is only allowed to be called by Lazy"); Executor* ex = continuation.promise()._executor; Executor::Context ctx = Executor::NULLCTX; if (ex != nullptr) { ctx = ex->checkout(); } future_.setContinuation([continuation, ex, ctx](Try<T>&& t) mutable { if (ex != nullptr) { ex->checkin(continuation, ctx); } else { continuation.resume(); } }); } auto await_resume() { if constexpr (!std::is_same_v<T, void>) return std::move(future_.value()); } }; } // namespace coro::detail template <typename T> auto operator co_await(Future<T>&& future) { return coro::detail::FutureAwaiter<T>{std::move(future)}; } template <typename T> [[deprecated("Require an rvalue future.")]] auto operator co_await(T&& future) requires IsFuture<std::decay_t<T>>::value { return std::move(operator co_await(std::move(future))); } } // namespace async_simple #endif