5 #include <libcopp/utils/config/libcopp_build_features.h>
16 #if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
18 LIBCOPP_COPP_NAMESPACE_BEGIN
20 LIBCOPP_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)
30 LIBCOPP_COPP_API promise_caller_manager::~promise_caller_manager() {}
32 LIBCOPP_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_set>(callers_)) {
39 std::get<multi_caller_set>(callers_).insert(delegate);
43 if (!std::get<handle_delegate>(callers_)) {
44 std::get<handle_delegate>(callers_) = delegate;
49 multi_caller_set callers;
50 callers.insert(std::get<handle_delegate>(callers_));
51 callers.insert(delegate);
52 callers_.emplace<multi_caller_set>(std::move(callers));
54 if (!unique_caller_.handle) {
55 unique_caller_ = delegate;
59 if (!multiple_callers_) {
60 multiple_callers_.reset(
new multi_caller_set());
62 multiple_callers_->insert(delegate);
66 LIBCOPP_COPP_API
bool promise_caller_manager::remove_caller(handle_delegate delegate) noexcept {
67 bool has_caller =
false;
69 # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
70 if (std::holds_alternative<multi_caller_set>(callers_)) {
71 has_caller = std::get<multi_caller_set>(callers_).erase(delegate) > 0;
75 if (std::get<handle_delegate>(callers_).handle == delegate.handle) {
76 std::get<handle_delegate>(callers_) =
nullptr;
80 if (unique_caller_.handle == delegate.handle) {
81 unique_caller_ =
nullptr;
86 if (multiple_callers_) {
87 has_caller = multiple_callers_->erase(delegate) > 0;
95 LIBCOPP_COPP_API
size_t promise_caller_manager::resume_callers() {
96 size_t resume_count = 0;
97 # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
98 if (std::holds_alternative<handle_delegate>(callers_)) {
99 auto caller = std::get<handle_delegate>(callers_);
100 std::get<handle_delegate>(callers_) =
nullptr;
101 if (caller.handle && !caller.handle.done() &&
102 (
nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) {
103 caller.handle.resume();
106 }
else if (std::holds_alternative<multi_caller_set>(callers_)) {
107 multi_caller_set callers;
108 callers.swap(std::get<multi_caller_set>(callers_));
109 for (
auto &caller : callers) {
110 if (caller.handle && !caller.handle.done() &&
111 (
nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) {
112 type_erased_handle_type handle = caller.handle;
119 auto unique_caller = unique_caller_;
120 unique_caller_ =
nullptr;
121 std::unique_ptr<multi_caller_set> multiple_callers;
122 multiple_callers.swap(multiple_callers_);
125 if (unique_caller.handle && !unique_caller.handle.done() &&
126 (
nullptr == unique_caller.promise || !unique_caller.promise->check_flag(promise_flag::kDestroying))) {
127 unique_caller.handle.resume();
131 if (multiple_callers) {
132 for (
auto &caller : *multiple_callers) {
133 if (caller.handle && !caller.handle.done() &&
134 (
nullptr == caller.promise || !caller.promise->check_flag(promise_flag::kDestroying))) {
135 type_erased_handle_type handle = caller.handle;
145 LIBCOPP_COPP_API
bool promise_caller_manager::has_multiple_callers()
const noexcept {
146 # if defined(LIBCOPP_MACRO_ENABLE_STD_VARIANT) && LIBCOPP_MACRO_ENABLE_STD_VARIANT
147 if (std::holds_alternative<handle_delegate>(callers_)) {
149 }
else if (std::holds_alternative<multi_caller_set>(callers_)) {
150 return std::get<multi_caller_set>(callers_).size() > 1;
155 if (unique_caller_.handle && !unique_caller_.handle.done() &&
156 (
nullptr == unique_caller_.promise || !unique_caller_.promise->check_flag(promise_flag::kDestroying))) {
160 if (multiple_callers_) {
161 count += multiple_callers_->size();
167 LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::pick_promise_status_awaitable() noexcept
168 :
data(promise_status::kInvalid) {}
170 LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::pick_promise_status_awaitable(
171 promise_status status) noexcept
174 LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::pick_promise_status_awaitable(
175 pick_promise_status_awaitable &&other) noexcept
176 :
data(other.data) {}
178 LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable &
179 promise_base_type::pick_promise_status_awaitable::operator=(pick_promise_status_awaitable &&other) noexcept {
184 LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable::~pick_promise_status_awaitable() {}
186 LIBCOPP_COPP_API promise_base_type::promise_base_type()
187 : flags_(0), status_{promise_status::kCreated}, current_waiting_{nullptr} {}
189 LIBCOPP_COPP_API promise_base_type::~promise_base_type() {}
191 LIBCOPP_COPP_API
bool promise_base_type::is_waiting()
const noexcept {
192 return current_waiting_ || check_flag(promise_flag::kInternalWaitting);
195 LIBCOPP_COPP_API
void promise_base_type::set_waiting_handle(std::nullptr_t) noexcept { current_waiting_ =
nullptr; }
197 LIBCOPP_COPP_API
void promise_base_type::set_waiting_handle(handle_delegate handle) { current_waiting_ = handle; }
199 LIBCOPP_COPP_API
void promise_base_type::resume_waiting(handle_delegate current_delegate,
bool inherit_status) {
201 auto waiting_delegate = current_waiting_;
204 if (waiting_delegate.handle && !waiting_delegate.handle.done()) {
205 current_waiting_ =
nullptr;
207 if (
nullptr != waiting_delegate.promise) {
208 waiting_delegate.promise->remove_caller(current_delegate, inherit_status);
210 waiting_delegate.handle.resume();
211 }
else if (current_delegate.handle && !current_delegate.handle.done() &&
212 check_flag(promise_flag::kInternalWaitting)) {
214 current_delegate.handle.resume();
218 LIBCOPP_COPP_API promise_base_type::pick_promise_status_awaitable promise_base_type::yield_value(
219 pick_promise_status_awaitable &&args)
const noexcept {
220 args.data = get_status();
221 return pick_promise_status_awaitable{args.data};
224 LIBCOPP_COPP_API
void promise_base_type::add_caller(handle_delegate delegate) noexcept {
225 caller_manager_.add_caller(delegate);
228 LIBCOPP_COPP_API
void promise_base_type::remove_caller(handle_delegate delegate,
bool inherit_status) noexcept {
229 bool remove_caller_success = caller_manager_.remove_caller(delegate);
230 if (remove_caller_success && inherit_status &&
nullptr != delegate.promise && get_status() < promise_status::kDone &&
231 delegate.promise->get_status() > promise_status::kDone) {
232 set_status(delegate.promise->get_status());
236 LIBCOPP_COPP_API
void promise_base_type::resume_callers() { caller_manager_.resume_callers(); }
238 LIBCOPP_COPP_API awaitable_base_type::awaitable_base_type() : caller_{nullptr} {}
239 LIBCOPP_COPP_API awaitable_base_type::~awaitable_base_type() {}
241 LIBCOPP_COPP_API promise_base_type::handle_delegate awaitable_base_type::get_caller()
const noexcept {
return caller_; }
243 LIBCOPP_COPP_API
void awaitable_base_type::set_caller(promise_base_type::handle_delegate caller) noexcept {
247 LIBCOPP_COPP_API
void awaitable_base_type::set_caller(std::nullptr_t) noexcept { caller_ =
nullptr; }
249 LIBCOPP_COPP_NAMESPACE_END
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())