Skip to content

Commit

Permalink
把 awaitable 和 awaiter 的概念进行分离。
Browse files Browse the repository at this point in the history
  • Loading branch information
microcai committed Oct 21, 2024
1 parent 0dca587 commit 9075f6a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 26 deletions.
67 changes: 43 additions & 24 deletions include/ucoro/awaitable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ namespace ucoro
template<typename T>
struct awaitable;

template<typename T>
struct awaitable_awaiter;

template<typename T>
struct awaitable_promise;

Expand Down Expand Up @@ -344,7 +347,7 @@ namespace ucoro
// 调用 co_await local_storage_t<T>
return local_storage_awaiter<traits::local_storage_value_type<std::decay_t<A>>>{this};
}
else if constexpr (concepts::is_awaitable_v<A>)
else if constexpr ( concepts::is_awaitable_v<std::decay_t<A>> )
{
// 调用 co_await awaitable<T>; 或者其他有三件套的类型
static_assert(std::is_rvalue_reference_v<A&&>, "co_await must be used on rvalue");
Expand All @@ -358,7 +361,7 @@ namespace ucoro
}
else
{
static_assert(0, "co_await must been used on an awaitable");
static_assert(0, "co_await must be called on an awaitable type");
}
}

Expand Down Expand Up @@ -419,28 +422,6 @@ namespace ucoro
awaitable& operator=(const awaitable&) = delete;
awaitable& operator=(awaitable&) = delete;

constexpr bool await_ready() const noexcept
{
return false;
}

T await_resume()
{
return current_coro_handle_.promise().get_value();
}

template<typename PromiseType>
auto await_suspend(std::coroutine_handle<PromiseType> continuation)
{
if constexpr (concepts::awaitable_promise_type<PromiseType>)
{
current_coro_handle_.promise().local_ = continuation.promise().local_;
}

current_coro_handle_.promise().continuation_ = continuation;
return current_coro_handle_;
}

void set_local(std::any local)
{
assert("local has value" && !current_coro_handle_.promise().local_);
Expand Down Expand Up @@ -500,9 +481,47 @@ namespace ucoro
return launched_coro;
}

awaitable_awaiter<T> operator co_await ()
{
return awaitable_awaiter<T>{this};
}

std::coroutine_handle<promise_type> current_coro_handle_;
};

//////////////////////////////////////////////////////////////////////////
// awaitable 的等待器
template<typename T>
struct awaitable_awaiter
{
awaitable<T>* this_;

constexpr bool await_ready() const noexcept
{
return false;
}

T await_resume()
{
return this_->current_coro_handle_.promise().get_value();
}

template<typename PromiseType>
auto await_suspend(std::coroutine_handle<PromiseType> continuation)
{
if constexpr (concepts::awaitable_promise_type<PromiseType>)
{
auto& calee_promise = this_->current_coro_handle_.promise();
auto& caller_promise = continuation.promise();
calee_promise.local_ = caller_promise.local_;
}

this_->current_coro_handle_.promise().continuation_ = continuation;
return this_->current_coro_handle_;
}

};

//////////////////////////////////////////////////////////////////////////

template<typename T>
Expand Down
4 changes: 2 additions & 2 deletions tests/test3/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ int main(int argc, char **argv)
static_assert(ucoro::concepts::is_awaiter_v<CallbackAwaiterType0>, "not a coroutine");
static_assert(ucoro::concepts::is_awaiter_v<CallbackAwaiterType1>, "not a coroutine");

static_assert(ucoro::concepts::is_awaiter_v<ucoro::awaitable<void>>, "not a coroutine");
static_assert(ucoro::concepts::is_awaiter_v<ucoro::awaitable<int>>, "not a coroutine");
static_assert(ucoro::concepts::is_awaiter_v<ucoro::awaitable_awaiter<void>>, "not a coroutine");
static_assert(ucoro::concepts::is_awaiter_v<ucoro::awaitable_awaiter<int>>, "not a coroutine");

static_assert(!ucoro::concepts::is_awaiter_v<int>, "not a coroutine");

Expand Down

0 comments on commit 9075f6a

Please sign in to comment.