5#include <libcopp/utils/config/libcopp_build_features.h>
16#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
18LIBCOPP_COPP_NAMESPACE_BEGIN
20LIBCOPP_COPP_API promise_caller_manager::promise_caller_manager()
22# if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
23 callers_(handle_delegate{nullptr})
25 unique_caller_(nullptr)
30LIBCOPP_COPP_API promise_caller_manager::~promise_caller_manager() {}
32LIBCOPP_COPP_API
void promise_caller_manager::add_caller(handle_delegate delegate)
noexcept {
33 if (!delegate.handle || delegate.handle.done()) {
37# if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
38 if (std::holds_alternative<multi_caller_container>(callers_)) {
39 std::get<multi_caller_container>(callers_).add(delegate);
43 if (!std::get<handle_delegate>(callers_)) {
44 std::get<handle_delegate>(callers_) = delegate;
48 if (std::get<handle_delegate>(callers_) == delegate) {
53 multi_caller_container callers;
54 callers.add(std::get<handle_delegate>(callers_));
55 callers.add(delegate);
56 callers_.emplace<multi_caller_container>(std::move(callers));
59 if (!unique_caller_.handle && (!multiple_callers_ || multiple_callers_->size() == 0)) {
60 unique_caller_ = delegate;
64 if (unique_caller_ == delegate) {
68 if (!multiple_callers_) {
69 multiple_callers_.reset(
new multi_caller_container());
71 multiple_callers_->add(delegate);
75LIBCOPP_COPP_API
bool promise_caller_manager::remove_caller(handle_delegate delegate)
noexcept {
76 bool has_caller =
false;
78# if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
79 if (std::holds_alternative<multi_caller_container>(callers_)) {
80 has_caller = std::get<multi_caller_container>(callers_).remove(delegate);
84 if (std::get<handle_delegate>(callers_).handle == delegate.handle) {
85 std::get<handle_delegate>(callers_) =
nullptr;
89 if (unique_caller_.handle == delegate.handle) {
90 unique_caller_ =
nullptr;
95 if (multiple_callers_) {
96 has_caller = multiple_callers_->remove(delegate);
104LIBCOPP_COPP_API
size_t promise_caller_manager::resume_callers() {
105 size_t resume_count = 0;
106# if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
107 if (std::holds_alternative<handle_delegate>(callers_)) {
108 auto caller = std::get<handle_delegate>(callers_);
109 std::get<handle_delegate>(callers_) =
nullptr;
110 if (caller.handle && !caller.handle.done() &&
111 (
nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) {
112 caller.handle.resume();
115 }
else if (std::holds_alternative<multi_caller_container>(callers_)) {
116 multi_caller_container callers;
117 callers.swap(std::get<multi_caller_container>(callers_));
118 for (
auto &caller : callers.callers) {
119 if (caller.handle && !caller.handle.done() &&
120 (
nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) {
121 type_erased_handle_type handle = caller.handle;
128 auto unique_caller = unique_caller_;
129 unique_caller_ =
nullptr;
130 std::unique_ptr<multi_caller_container> multiple_callers;
131 multiple_callers.swap(multiple_callers_);
134 if (unique_caller.handle && !unique_caller.handle.done() &&
135 (
nullptr == unique_caller.promise || !unique_caller.promise->check_flag(promise_flag::kDestroying))) {
136 unique_caller.handle.resume();
140 if (multiple_callers) {
141 for (
auto &caller : multiple_callers->callers) {
142 if (caller.handle && !caller.handle.done() &&
143 (
nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) {
144 type_erased_handle_type handle = caller.handle;
154LIBCOPP_COPP_API
bool promise_caller_manager::has_multiple_callers() const noexcept {
155# if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
156 if (std::holds_alternative<handle_delegate>(callers_)) {
158 }
else if (std::holds_alternative<multi_caller_container>(callers_)) {
159 return std::get<multi_caller_container>(callers_).size() > 1;
164 if (unique_caller_.handle && !unique_caller_.handle.done() &&
165 (
nullptr == unique_caller_.promise || !unique_caller_.promise->check_flag(promise_flag::kDestroying))) {
169 if (multiple_callers_) {
170 count += multiple_callers_->size();
176LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::pick_promise_status_awaitable() noexcept
177 : data(promise_status::kInvalid) {}
179LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::pick_promise_status_awaitable(
180 promise_status status) noexcept
183LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::pick_promise_status_awaitable(
184 pick_promise_status_awaitable &&other) noexcept
185 :
data(other.data) {}
187LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable &
188promise_base_type::pick_promise_status_awaitable::operator=(pick_promise_status_awaitable &&other)
noexcept {
193LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::~pick_promise_status_awaitable() {}
195LIBCOPP_COPP_API promise_base_type::promise_base_type()
196 : flags_(0), status_{promise_status::kCreated}, current_waiting_{nullptr} {}
198LIBCOPP_COPP_API promise_base_type::~promise_base_type() {}
200LIBCOPP_COPP_API
bool promise_base_type::is_waiting() const noexcept {
201 return current_waiting_ || check_flag(promise_flag::kInternalWaitting);
204LIBCOPP_COPP_API
void promise_base_type::set_waiting_handle(std::nullptr_t)
noexcept { current_waiting_ =
nullptr; }
206LIBCOPP_COPP_API
void promise_base_type::set_waiting_handle(handle_delegate handle) { current_waiting_ = handle; }
208LIBCOPP_COPP_API
void promise_base_type::resume_waiting(handle_delegate current_delegate,
bool inherit_status) {
210 auto waiting_delegate = current_waiting_;
213 if (waiting_delegate.handle && !waiting_delegate.handle.done()) {
214 current_waiting_ =
nullptr;
216 if (
nullptr != waiting_delegate.promise) {
217 waiting_delegate.promise->remove_caller(current_delegate, inherit_status);
219 waiting_delegate.handle.resume();
220 }
else if (current_delegate.handle && !current_delegate.handle.done() &&
221 check_flag(promise_flag::kInternalWaitting)) {
223 current_delegate.handle.resume();
227LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable promise_base_type::yield_value(
228 pick_promise_status_awaitable &&args)
const noexcept {
229 args.data = get_status();
230 return pick_promise_status_awaitable{args.data};
233LIBCOPP_COPP_API
void promise_base_type::add_caller(handle_delegate delegate)
noexcept {
234 caller_manager_.add_caller(delegate);
237LIBCOPP_COPP_API
void promise_base_type::remove_caller(handle_delegate delegate,
bool inherit_status)
noexcept {
238 bool remove_caller_success = caller_manager_.remove_caller(delegate);
239 if (remove_caller_success && inherit_status &&
nullptr != delegate.promise && get_status() < promise_status::kDone &&
240 delegate.promise->get_status() > promise_status::kDone) {
241 set_status(delegate.promise->get_status());
245LIBCOPP_COPP_API
void promise_base_type::resume_callers() { caller_manager_.resume_callers(); }
247LIBCOPP_COPP_API awaitable_base_type::awaitable_base_type() : caller_{nullptr} {}
248LIBCOPP_COPP_API awaitable_base_type::~awaitable_base_type() {}
250LIBCOPP_COPP_API promise_base_type::handle_delegate awaitable_base_type::get_caller() const noexcept {
return caller_; }
252LIBCOPP_COPP_API
void awaitable_base_type::set_caller(promise_base_type::handle_delegate caller)
noexcept {
256LIBCOPP_COPP_API
void awaitable_base_type::set_caller(std::nullptr_t)
noexcept { caller_ =
nullptr; }
258LIBCOPP_COPP_NAMESPACE_END
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())