mirror of
https://github.com/boostorg/asio.git
synced 2026-01-27 18:42:07 +00:00
Allow the awaitable to be stored and co_await applied to it later.
This commit is contained in:
@@ -149,20 +149,20 @@ public:
|
||||
// Support for co_await keyword.
|
||||
bool await_ready() const noexcept
|
||||
{
|
||||
return false;
|
||||
return awaitee_->ready();
|
||||
}
|
||||
|
||||
// Support for co_await keyword.
|
||||
void await_suspend(detail::coroutine_handle<detail::awaiter<Executor>> h)
|
||||
{
|
||||
awaitee_->start(&h.promise(), h);
|
||||
awaitee_->attach_caller(&h.promise(), h);
|
||||
}
|
||||
|
||||
// Support for co_await keyword.
|
||||
template <class U>
|
||||
void await_suspend(detail::coroutine_handle<detail::awaitee<U, Executor>> h)
|
||||
{
|
||||
awaitee_->start(h.promise().top(), h);
|
||||
awaitee_->attach_caller(h.promise().top(), h);
|
||||
}
|
||||
|
||||
// Support for co_await keyword.
|
||||
|
||||
@@ -36,36 +36,6 @@ namespace asio {
|
||||
namespace experimental {
|
||||
namespace detail {
|
||||
|
||||
// Helper for returning an awaitable "always ready" value.
|
||||
template <typename T>
|
||||
class await_ready_value
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit await_ready_value(Args&&... args)
|
||||
: value_(std::forward<Args>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
bool await_ready() const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename U, typename Ex>
|
||||
void await_suspend(coroutine_handle<detail::awaitee<U, Ex>>) const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
T await_resume()
|
||||
{
|
||||
return std::move(value_);
|
||||
}
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
// Promise object for coroutine at top of thread-of-execution "stack".
|
||||
template <typename Executor>
|
||||
class awaiter
|
||||
@@ -132,7 +102,12 @@ public:
|
||||
coroutine_handle<awaiter>::from_promise(*this).destroy();
|
||||
}
|
||||
|
||||
void rethrow_exception()
|
||||
void unhandled_exception()
|
||||
{
|
||||
pending_exception_ = std::current_exception();
|
||||
}
|
||||
|
||||
void rethrow_unhandled_exception()
|
||||
{
|
||||
if (pending_exception_)
|
||||
{
|
||||
@@ -141,19 +116,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void unhandled_exception()
|
||||
{
|
||||
pending_exception_ = std::current_exception();
|
||||
}
|
||||
|
||||
void set_except(std::exception_ptr e)
|
||||
{
|
||||
pending_exception_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t ref_count_ = 0;
|
||||
std::exception_ptr pending_exception_;
|
||||
std::exception_ptr pending_exception_ = nullptr;
|
||||
alignas(Executor) unsigned char executor_[sizeof(Executor)];
|
||||
bool has_executor_ = false;
|
||||
};
|
||||
@@ -183,7 +148,7 @@ public:
|
||||
|
||||
auto initial_suspend()
|
||||
{
|
||||
return std::experimental::suspend_always();
|
||||
return std::experimental::suspend_never();
|
||||
}
|
||||
|
||||
struct final_suspender
|
||||
@@ -212,7 +177,7 @@ public:
|
||||
|
||||
void set_except(std::exception_ptr e)
|
||||
{
|
||||
awaiter_->set_except(e);
|
||||
pending_exception_ = e;
|
||||
}
|
||||
|
||||
void unhandled_exception()
|
||||
@@ -220,6 +185,15 @@ public:
|
||||
set_except(std::current_exception());
|
||||
}
|
||||
|
||||
void rethrow_exception()
|
||||
{
|
||||
if (pending_exception_)
|
||||
{
|
||||
std::exception_ptr ex = std::exchange(pending_exception_, nullptr);
|
||||
std::rethrow_exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
awaiter<Executor>* top()
|
||||
{
|
||||
return awaiter_;
|
||||
@@ -230,34 +204,94 @@ public:
|
||||
return caller_;
|
||||
}
|
||||
|
||||
bool ready() const
|
||||
{
|
||||
return ready_;
|
||||
}
|
||||
|
||||
void wake_caller()
|
||||
{
|
||||
if (caller_)
|
||||
caller_.resume();
|
||||
else
|
||||
ready_ = true;
|
||||
}
|
||||
|
||||
await_ready_value<Executor> await_transform(
|
||||
this_coro::executor_t) const noexcept
|
||||
class awaitable_executor
|
||||
{
|
||||
return await_ready_value<Executor>(awaiter_->get_executor());
|
||||
public:
|
||||
explicit awaitable_executor(const awaitee_base* a)
|
||||
: this_(a)
|
||||
{
|
||||
}
|
||||
|
||||
bool await_ready() const noexcept
|
||||
{
|
||||
return this_->awaiter_ != nullptr;
|
||||
}
|
||||
|
||||
template <typename U, typename Ex>
|
||||
void await_suspend(coroutine_handle<detail::awaitee<U, Ex>>) const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
Executor await_resume()
|
||||
{
|
||||
return this_->awaiter_->get_executor();
|
||||
}
|
||||
|
||||
private:
|
||||
const awaitee_base* this_;
|
||||
};
|
||||
|
||||
awaitable_executor await_transform(this_coro::executor_t) const noexcept
|
||||
{
|
||||
return awaitable_executor(this);
|
||||
}
|
||||
|
||||
await_ready_value<await_token<Executor>> await_transform(
|
||||
this_coro::token_t) const noexcept
|
||||
class awaitable_token
|
||||
{
|
||||
return await_ready_value<await_token<Executor>>(
|
||||
await_token<Executor>(awaiter_));
|
||||
public:
|
||||
explicit awaitable_token(const awaitee_base* a)
|
||||
: this_(a)
|
||||
{
|
||||
}
|
||||
|
||||
bool await_ready() const noexcept
|
||||
{
|
||||
return this_->awaiter_ != nullptr;
|
||||
}
|
||||
|
||||
template <typename U, typename Ex>
|
||||
void await_suspend(coroutine_handle<detail::awaitee<U, Ex>>) const noexcept
|
||||
{
|
||||
}
|
||||
|
||||
await_token<Executor> await_resume()
|
||||
{
|
||||
return await_token<Executor>(this_->awaiter_);
|
||||
}
|
||||
|
||||
private:
|
||||
const awaitee_base* this_;
|
||||
};
|
||||
|
||||
awaitable_token await_transform(this_coro::token_t) const noexcept
|
||||
{
|
||||
return awaitable_token(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T await_transform(T t) const
|
||||
T await_transform(T&& t) const
|
||||
{
|
||||
return t;
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
protected:
|
||||
awaiter<Executor>* awaiter_ = nullptr;
|
||||
coroutine_handle<void> caller_ = nullptr;
|
||||
std::exception_ptr pending_exception_ = nullptr;
|
||||
bool ready_ = false;
|
||||
};
|
||||
|
||||
// Promise object for coroutines further down the thread-of-execution "stack".
|
||||
@@ -296,11 +330,11 @@ public:
|
||||
T get()
|
||||
{
|
||||
this->caller_ = nullptr;
|
||||
this->awaiter_->rethrow_exception();
|
||||
this->rethrow_exception();
|
||||
return std::move(*static_cast<T*>(static_cast<void*>(result_)));
|
||||
}
|
||||
|
||||
void start(awaiter<Executor>* a, coroutine_handle<void> h)
|
||||
void attach_caller(awaiter<Executor>* a, coroutine_handle<void> h)
|
||||
{
|
||||
this->awaiter_ = a;
|
||||
this->caller_ = h;
|
||||
@@ -330,10 +364,10 @@ public:
|
||||
void get()
|
||||
{
|
||||
this->caller_ = nullptr;
|
||||
this->awaiter_->rethrow_exception();
|
||||
this->rethrow_exception();
|
||||
}
|
||||
|
||||
void start(awaiter<Executor>* a, coroutine_handle<void> h)
|
||||
void attach_caller(awaiter<Executor>* a, coroutine_handle<void> h)
|
||||
{
|
||||
this->awaiter_ = a;
|
||||
this->caller_ = h;
|
||||
@@ -434,7 +468,7 @@ public:
|
||||
typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
|
||||
this->awaitee_->return_void();
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -455,7 +489,7 @@ public:
|
||||
else
|
||||
this->awaitee_->return_void();
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -474,7 +508,7 @@ public:
|
||||
else
|
||||
this->awaitee_->return_void();
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -491,7 +525,7 @@ public:
|
||||
typename awaiter<Executor>::ptr ptr(std::move(this->awaiter_));
|
||||
this->awaitee_->return_value(std::forward<Arg>(arg));
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -511,7 +545,7 @@ public:
|
||||
else
|
||||
this->awaitee_->return_value(std::forward<Arg>(arg));
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -531,7 +565,7 @@ public:
|
||||
else
|
||||
this->awaitee_->return_value(std::forward<Arg>(arg));
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -549,7 +583,7 @@ public:
|
||||
this->awaitee_->return_value(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -570,7 +604,7 @@ public:
|
||||
this->awaitee_->return_value(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -591,7 +625,7 @@ public:
|
||||
this->awaitee_->return_value(
|
||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
this->awaitee_->wake_caller();
|
||||
ptr->rethrow_exception();
|
||||
ptr->rethrow_unhandled_exception();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user