17#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
20struct task_future_private_data {
24using task_future_int_type = cotask::task_future<int, task_future_private_data>;
25using task_future_void_type = cotask::task_future<void, task_future_private_data>;
26using task_future_int_type_no_private_data = cotask::task_future<int, void>;
27using task_future_void_type_no_private_data = cotask::task_future<void, void>;
28using callable_future_int_type = copp::callable_future<int>;
29using callable_future_void_type = copp::callable_future<void>;
30using generator_future_int_type = copp::generator_future<int>;
31using generator_future_void_type = copp::generator_future<void>;
33std::list<generator_future_int_type::context_pointer_type> g_task_future_pending_int_contexts;
34std::list<generator_future_void_type::context_pointer_type> g_task_future_pending_void_contexts;
35size_t g_task_future_resume_generator_count = 0;
36size_t g_task_future_suspend_generator_count = 0;
38static size_t resume_pending_contexts(std::list<int> values,
int max_count = 32767) {
40 while (max_count > 0 &&
41 (!g_task_future_pending_int_contexts.empty() || !g_task_future_pending_void_contexts.empty())) {
43 if (!g_task_future_pending_int_contexts.empty()) {
44 auto ctx = *g_task_future_pending_int_contexts.begin();
45 g_task_future_pending_int_contexts.pop_front();
47 if (!values.empty()) {
48 int val = values.front();
58 if (!g_task_future_pending_void_contexts.empty()) {
59 auto ctx = *g_task_future_pending_void_contexts.begin();
60 g_task_future_pending_void_contexts.pop_front();
70static void generator_int_suspend_callback(generator_future_int_type::context_pointer_type ctx) {
71 ++g_task_future_suspend_generator_count;
72 g_task_future_pending_int_contexts.push_back(ctx);
74static void generator_int_resume_callback(
const generator_future_int_type::context_type &) {
75 ++g_task_future_resume_generator_count;
78static callable_future_int_type task_future_func_int_l1(
int inout) {
79 CASE_MSG_INFO() <<
"callable inner future ready int: " << inout << std::endl;
83static callable_future_int_type task_future_func_int_l2(
int inout) {
84 generator_future_int_type generator{generator_int_suspend_callback, generator_int_resume_callback};
85 auto gen_res =
co_await generator;
89 co_return inout + gen_res;
92static callable_future_int_type task_future_func_await_int() {
93 auto v = task_future_func_int_l1(3);
94 auto u = task_future_func_int_l2(11);
95 int x = (
co_await v +
co_await u);
99static task_future_int_type task_func_await_int() {
100 auto current_status =
co_yield task_future_void_type::yield_status();
101 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
102 auto private_data =
co_yield task_future_int_type::yield_private_data();
103 private_data->data = 121000;
106 auto v = task_future_func_await_int();
112static callable_future_int_type task_future_func_no_wait_int() {
113 auto v = task_future_func_int_l1(7);
114 auto u = task_future_func_int_l1(19);
115 int x = (
co_await v +
co_await u);
119static task_future_int_type task_func_no_wait_int() {
120 auto current_status =
co_yield task_future_void_type::yield_status();
121 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
122 auto private_data =
co_yield cotask::task_private_data<task_future_private_data>();
123 private_data->data = 121000;
126 auto v = task_future_func_no_wait_int();
132static void generator_void_suspend_callback(generator_future_void_type::context_pointer_type ctx) {
133 ++g_task_future_suspend_generator_count;
134 g_task_future_pending_void_contexts.push_back(ctx);
136static void generator_void_resume_callback(
const generator_future_void_type::context_type &) {
137 ++g_task_future_resume_generator_count;
140static callable_future_void_type task_future_func_void_l1() {
141 CASE_MSG_INFO() <<
"callable inner future ready void" << std::endl;
145static callable_future_void_type task_future_func_void_l2() {
146 generator_future_void_type generator{generator_void_suspend_callback, generator_void_resume_callback};
151static callable_future_void_type task_future_func_await_void() {
152 auto v = task_future_func_void_l1();
153 auto u = task_future_func_void_l2();
159static task_future_void_type task_func_await_void() {
160 auto current_status =
co_yield task_future_void_type::yield_status();
161 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
162 auto private_data =
co_yield task_future_void_type::yield_private_data();
163 private_data->data = 123000;
166 auto v = task_future_func_await_void();
172static callable_future_void_type task_future_func_no_wait_void() {
173 auto v = task_future_func_void_l1();
174 auto u = task_future_func_void_l1();
180static task_future_void_type task_func_no_wait_void() {
181 auto current_status =
co_yield task_future_void_type::yield_status();
182 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
183 auto private_data =
co_yield cotask::task_private_data<task_future_private_data>();
184 private_data->data = 123000;
187 auto v = task_future_func_no_wait_void();
193static task_future_void_type_no_private_data task_func_await_pick_task_id(
194 task_future_void_type_no_private_data::id_type &output) {
195 output =
co_yield task_future_void_type_no_private_data::yield_task_id();
202CASE_TEST(task_promise, task_future_void_yield_task_id) {
203 task_future_void_type_no_private_data::id_type task_id = 0;
204 task_future_void_type_no_private_data t = task_func_await_pick_task_id(task_id);
216CASE_TEST(task_promise, task_future_integer_need_resume) {
217 size_t old_resume_generator_count = g_task_future_resume_generator_count;
218 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
220 task_future_int_type t = task_func_await_int();
221 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
230 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
237 resume_pending_contexts({100});
238 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
246 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
247 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
250CASE_TEST(task_promise, task_future_void_need_resume) {
251 size_t old_resume_generator_count = g_task_future_resume_generator_count;
252 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
254 task_future_void_type t = task_func_await_void();
255 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
264 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
271 resume_pending_contexts({100});
272 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
279 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
280 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
283CASE_TEST(task_promise, task_future_integer_no_resume) {
284 size_t old_resume_generator_count = g_task_future_resume_generator_count;
285 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
287 task_future_int_type t = task_func_no_wait_int();
288 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
297 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
305 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
306 CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
309CASE_TEST(task_promise, task_future_void_no_resume) {
310 size_t old_resume_generator_count = g_task_future_resume_generator_count;
311 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
313 task_future_void_type t = task_func_no_wait_void();
314 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
323 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
330 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
331 CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
335static task_future_int_type task_func_await_int_generator() {
336 generator_future_int_type generator{generator_int_suspend_callback, generator_int_resume_callback};
337 auto res =
co_await generator;
341static callable_future_int_type task_future_func_await_int_task() {
342 task_future_int_type t = task_func_await_int_generator();
344 auto res =
co_await t;
348static task_future_int_type task_func_await_int_task() {
349 task_future_int_type t = task_func_await_int_generator();
351 auto res =
co_await t;
356CASE_TEST(task_promise, callable_future_await_task) {
357 size_t old_resume_generator_count = g_task_future_resume_generator_count;
358 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
360 callable_future_int_type
f = task_future_func_await_int_task();
361 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(
f.get_status()));
365 resume_pending_contexts({1000});
366 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(
f.get_status()));
370 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
371 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
374CASE_TEST(task_promise, task_future_await_task) {
375 size_t old_resume_generator_count = g_task_future_resume_generator_count;
376 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
378 task_future_int_type t = task_func_await_int_task();
379 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
387 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
394 resume_pending_contexts({2000});
395 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
403 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
404 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
408std::list<generator_future_int_type::context_pointer_type> g_task_future_fifo_blocker_contexts;
409std::vector<int> g_task_future_fifo_resume_order;
411static void generator_fifo_blocker_suspend_callback(generator_future_int_type::context_pointer_type ctx) {
412 g_task_future_fifo_blocker_contexts.push_back(ctx);
414static void generator_fifo_blocker_resume_callback(
const generator_future_int_type::context_type &) {}
416static task_future_int_type task_func_fifo_blocker() {
417 generator_future_int_type generator{generator_fifo_blocker_suspend_callback, generator_fifo_blocker_resume_callback};
418 auto res =
co_await generator;
422static callable_future_int_type task_future_func_fifo_waiter(task_future_int_type waiting,
int index) {
423 int res =
co_await waiting;
425 g_task_future_fifo_resume_order.push_back(index);
431CASE_TEST(task_promise, task_future_multiple_callers_resume_fifo) {
432 g_task_future_fifo_blocker_contexts.clear();
433 g_task_future_fifo_resume_order.clear();
435 task_future_int_type blocker = task_func_fifo_blocker();
438 CASE_EXPECT_EQ(1,
static_cast<int>(g_task_future_fifo_blocker_contexts.size()));
440 constexpr int k_waiter_count = 8;
441 std::vector<callable_future_int_type> waiters;
442 for (
int index = 0; index < k_waiter_count; ++index) {
443 waiters.push_back(task_future_func_fifo_waiter(blocker, index));
450 auto pending_context = g_task_future_fifo_blocker_contexts.front();
451 g_task_future_fifo_blocker_contexts.pop_front();
452 pending_context->set_value(0);
455 CASE_EXPECT_EQ(k_waiter_count,
static_cast<int>(g_task_future_fifo_resume_order.size()));
456 for (
int index = 0; index < k_waiter_count; ++index) {
457 CASE_EXPECT_EQ(index, g_task_future_fifo_resume_order[
static_cast<size_t>(index)]);
462CASE_TEST(task_promise, task_future_multiple_callers_resume_fifo_after_first_killed) {
463 g_task_future_fifo_blocker_contexts.clear();
464 g_task_future_fifo_resume_order.clear();
466 task_future_int_type blocker = task_func_fifo_blocker();
468 callable_future_int_type waiter0 = task_future_func_fifo_waiter(blocker, 0);
469 callable_future_int_type waiter1 = task_future_func_fifo_waiter(blocker, 1);
480 callable_future_int_type waiter2 = task_future_func_fifo_waiter(blocker, 2);
482 CASE_EXPECT_EQ(1,
static_cast<int>(g_task_future_fifo_blocker_contexts.size()));
483 if (!g_task_future_fifo_blocker_contexts.empty()) {
484 auto pending_context = g_task_future_fifo_blocker_contexts.front();
485 g_task_future_fifo_blocker_contexts.pop_front();
486 pending_context->set_value(0);
492 CASE_EXPECT_EQ(2,
static_cast<int>(g_task_future_fifo_resume_order.size()));
493 if (g_task_future_fifo_resume_order.size() == 2) {
499CASE_TEST(task_promise, task_future_caller_manager_dedup_and_remove) {
500 g_task_future_fifo_blocker_contexts.clear();
501 g_task_future_fifo_resume_order.clear();
503 task_future_int_type blocker = task_func_fifo_blocker();
508 callable_future_int_type waiter0 = task_future_func_fifo_waiter(blocker, 0);
509 callable_future_int_type waiter1 = task_future_func_fifo_waiter(blocker, 1);
510 callable_future_int_type waiter2 = task_future_func_fifo_waiter(blocker, 2);
515 using caller_delegate = copp::promise_caller_manager::handle_delegate;
516 copp::promise_caller_manager manager;
520 manager.add_caller(caller_delegate{waiter0.get_internal_handle()});
521 manager.add_caller(caller_delegate{waiter0.get_internal_handle()});
525 CASE_EXPECT_FALSE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()}));
528 manager.add_caller(caller_delegate{waiter1.get_internal_handle()});
529 manager.add_caller(caller_delegate{waiter0.get_internal_handle()});
530 manager.add_caller(caller_delegate{waiter1.get_internal_handle()});
534 CASE_EXPECT_FALSE(manager.remove_caller(caller_delegate{waiter2.get_internal_handle()}));
537 CASE_EXPECT_TRUE(manager.remove_caller(caller_delegate{waiter0.get_internal_handle()}));
539 manager.add_caller(caller_delegate{waiter1.get_internal_handle()});
541 CASE_EXPECT_TRUE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()}));
542 CASE_EXPECT_FALSE(manager.remove_caller(caller_delegate{waiter1.get_internal_handle()}));
546 CASE_EXPECT_EQ(1,
static_cast<int>(g_task_future_fifo_blocker_contexts.size()));
547 if (!g_task_future_fifo_blocker_contexts.empty()) {
548 auto pending_context = g_task_future_fifo_blocker_contexts.front();
549 g_task_future_fifo_blocker_contexts.pop_front();
550 pending_context->set_value(0);
559static callable_future_int_type task_func_await_callable_and_be_killed() {
560 auto u = task_future_func_int_l2(13);
565static task_future_int_type task_func_await_and_be_killed_by_caller() {
566 auto v = task_func_await_callable_and_be_killed();
571std::shared_ptr<task_future_int_type> g_task_promise_killed_by_callee;
572static task_future_int_type task_func_await_and_be_killed_by_callee(task_future_int_type::task_status_type status) {
573 g_task_promise_killed_by_callee->kill(status);
574 auto v = task_func_await_callable_and_be_killed();
582CASE_TEST(task_promise, killed_by_caller) {
583 size_t old_resume_generator_count = g_task_future_resume_generator_count;
584 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
586 task_future_int_type t = task_func_await_and_be_killed_by_caller();
587 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
595 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
603 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kKilled),
static_cast<int>(t.get_status()));
609 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
611 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
612 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
614 resume_pending_contexts({100});
615 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
622 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
623 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
626CASE_TEST(task_promise, killed_by_callee) {
627 size_t old_resume_generator_count = g_task_future_resume_generator_count;
628 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
630 task_future_int_type t = task_func_await_and_be_killed_by_callee(copp::promise_status::kKilled);
631 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
638 g_task_promise_killed_by_callee = std::make_shared<task_future_int_type>(t);
640 g_task_promise_killed_by_callee.reset();
642 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kKilled),
static_cast<int>(t.get_status()));
648 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
650 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
651 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
653 resume_pending_contexts({100});
654 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
661 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
662 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
666CASE_TEST(task_promise, cancel_by_caller) {
667 size_t old_resume_generator_count = g_task_future_resume_generator_count;
668 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
670 task_future_int_type t = task_func_await_and_be_killed_by_caller();
671 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
679 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
687 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCancle),
static_cast<int>(t.get_status()));
693 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kCancle), *t.get_context()->data());
695 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
696 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
698 resume_pending_contexts({100});
699 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kCancle), *t.get_context()->data());
706 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
707 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
711CASE_TEST(task_promise, timeout_by_caller) {
712 size_t old_resume_generator_count = g_task_future_resume_generator_count;
713 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
715 task_future_int_type t = task_func_await_and_be_killed_by_caller();
716 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
724 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
732 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kTimeout),
static_cast<int>(t.get_status()));
738 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
740 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
741 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
743 resume_pending_contexts({100});
744 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
751 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
752 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
755CASE_TEST(task_promise, timeout_by_callee) {
756 size_t old_resume_generator_count = g_task_future_resume_generator_count;
757 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
759 task_future_int_type t = task_func_await_and_be_killed_by_callee(copp::promise_status::kTimeout);
760 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
767 g_task_promise_killed_by_callee = std::make_shared<task_future_int_type>(t);
769 g_task_promise_killed_by_callee.reset();
771 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kTimeout),
static_cast<int>(t.get_status()));
777 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
779 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
780 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
782 resume_pending_contexts({100});
783 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
790 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
791 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
795static task_future_int_type task_func_await_child_task_child() {
796 auto u = task_future_func_int_l2(53);
801static task_future_int_type task_func_await_child_task_parent(task_future_int_type &out) {
802 out = task_func_await_child_task_child();
803 int x =
co_await out;
807static task_future_int_type task_func_await_empty() {
808 task_future_int_type empty;
809 int x =
co_await empty;
816CASE_TEST(task_promise, kill_parent_only) {
817 size_t old_resume_generator_count = g_task_future_resume_generator_count;
818 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
820 task_future_int_type child;
821 task_future_int_type parent = task_func_await_child_task_parent(child);
822 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(parent.get_status()));
830 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(parent.get_status()));
837 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(child.get_status()));
838 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
839 CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
841 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
842 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
844 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(child.get_status()));
851 CASE_EXPECT_TRUE(parent.kill(task_future_int_type::task_status_type::kTimeout));
852 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kTimeout),
static_cast<int>(parent.get_status()));
858 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *parent.get_context()->data());
860 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(child.get_status()));
867 resume_pending_contexts({1000});
868 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *parent.get_context()->data());
875 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(child.get_status()));
883 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
884 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
888 task_future_int_type t = task_func_await_empty();
891 task_future_int_type empty;
895 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kInvalid),
static_cast<int>(empty.get_status()));
903CASE_TEST(task_promise, task_destroy_and_auto_resume) {
904 task_future_int_type parent;
906 task_future_int_type child;
907 parent = task_func_await_child_task_parent(child);
917 task_future_int_type move_child_assign = std::move(child);
925 task_future_int_type move_child_ctor{std::move(move_child_assign)};
929 task_future_int_type copy_child_assign = move_child_ctor;
930 task_future_int_type copy_child_ctor{move_child_ctor};
936 CASE_EXPECT_EQ(copy_child_assign.get_context(), copy_child_ctor.get_context());
937 CASE_EXPECT_EQ(copy_child_assign.get_context(), move_child_ctor.get_context());
939 CASE_EXPECT_EQ(copy_child_assign.get_id(), copy_child_ctor.get_id());
940 CASE_EXPECT_EQ(copy_child_assign.get_id(), move_child_ctor.get_id());
948 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *parent.get_context()->data());
950 resume_pending_contexts({});
954static task_future_int_type task_func_await_int_simple() {
955 auto u = task_future_func_int_l2(91);
960static task_future_void_type task_func_await_void_simple() {
961 auto u = task_future_func_void_l2();
966static callable_future_int_type task_func_callable_await_task_int_simple() {
967 auto u = task_func_await_int_simple();
975CASE_TEST(task_promise, forget_to_start) {
978 auto f = task_func_callable_await_task_int_simple();
981 resume_pending_contexts({});
984CASE_TEST(task_promise, callable_then_12_1_task_return_int_and_thenable_return_normal_int) {
985 auto t = task_func_await_int_simple();
986 auto f = t.then([](task_future_int_type::context_pointer_type, task_future_int_type::value_type value) {
996 resume_pending_contexts({2000});
1002CASE_TEST(task_promise, callable_then_12_2_task_return_int_and_thenable_return_normal_void) {
1003 auto t = task_func_await_int_simple();
1004 auto f = t.then([](
const task_future_int_type::context_pointer_type &, task_future_int_type::value_type value) {
1013 resume_pending_contexts({2000});
1017CASE_TEST(task_promise, callable_then_12_3_task_return_int_and_thenable_return_callable_int) {
1018 auto t = task_func_await_int_simple();
1019 auto f = t.then([](task_future_int_type::context_pointer_type &&,
1020 task_future_int_type::value_type value) -> copp::callable_future<int> {
1022 CASE_MSG_INFO() <<
"thenable return callable_future<int>" << std::endl;
1030 resume_pending_contexts({2000});
1036CASE_TEST(task_promise, callable_then_12_4_task_return_int_and_thenable_return_callable_void) {
1037 auto t = task_func_await_int_simple();
1038 auto f = t.then([](
const task_future_int_type::context_pointer_type &,
1039 task_future_int_type::value_type value) -> copp::callable_future<void> {
1041 CASE_MSG_INFO() <<
"thenable return callable_future<void>" << std::endl;
1049 resume_pending_contexts({2000});
1053CASE_TEST(task_promise, callable_then_12_5_task_return_int_and_thenable_return_callable_int) {
1054 auto t = task_func_await_int_simple();
1055 auto f = t.then([](task_future_int_type::context_pointer_type,
1056 task_future_int_type::value_type value) -> cotask::task_future<int, void> {
1058 CASE_MSG_INFO() <<
"thenable return task_future<int>" << std::endl;
1066 resume_pending_contexts({2000});
1072CASE_TEST(task_promise, callable_then_12_6_task_return_int_and_thenable_return_callable_void) {
1073 auto t = task_func_await_int_simple();
1074 auto f = t.then([](task_future_int_type::context_pointer_type &&,
1075 task_future_int_type::value_type value) -> cotask::task_future<void, void> {
1077 CASE_MSG_INFO() <<
"thenable return task_future<void>" << std::endl;
1085 resume_pending_contexts({2000});
1089CASE_TEST(task_promise, callable_then_12_7_task_return_void_and_thenable_return_normal_int) {
1090 auto t = task_func_await_void_simple();
1091 auto f = t.then([](task_future_void_type::context_pointer_type) {
1100 resume_pending_contexts({});
1106CASE_TEST(task_promise, callable_then_12_8_task_return_void_and_thenable_return_normal_void) {
1107 auto t = task_func_await_void_simple();
1108 auto f = t.then([](
const task_future_void_type::context_pointer_type &) {
1116 resume_pending_contexts({});
1120CASE_TEST(task_promise, callable_then_12_9_task_return_void_and_thenable_return_callable_int) {
1121 auto t = task_func_await_void_simple();
1122 auto f = t.then([](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
1123 CASE_MSG_INFO() <<
"thenable return callable_future<int>" << std::endl;
1131 resume_pending_contexts({});
1137CASE_TEST(task_promise, callable_then_12_10_task_return_void_and_thenable_return_callable_void) {
1138 auto t = task_func_await_void_simple();
1139 auto f = t.then([](
const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
1140 CASE_MSG_INFO() <<
"thenable return callable_future<void>" << std::endl;
1148 resume_pending_contexts({});
1152CASE_TEST(task_promise, callable_then_12_11_task_return_void_and_thenable_return_callable_int) {
1153 auto t = task_func_await_void_simple();
1154 auto f = t.then([](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1155 CASE_MSG_INFO() <<
"thenable return task_future<int>" << std::endl;
1163 resume_pending_contexts({});
1169CASE_TEST(task_promise, callable_then_12_12_task_return_void_and_thenable_return_callable_void) {
1170 auto t = task_func_await_void_simple();
1171 auto f = t.then([](
const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1172 CASE_MSG_INFO() <<
"thenable return task_future<void>" << std::endl;
1180 resume_pending_contexts({});
1184CASE_TEST(task_promise, then_kill_task) {
1185 auto t = task_func_await_int_simple();
1186 auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1188 static_cast<int>(task_future_int_type::task_status_type::kTimeout));
1189 CASE_EXPECT_EQ(-
static_cast<int>(task_future_int_type::task_status_type::kTimeout), value);
1190 CASE_MSG_INFO() <<
"thenable of timeout task return int" << std::endl;
1198 t.kill(task_future_int_type::task_status_type::kTimeout);
1201 CASE_EXPECT_EQ(-
static_cast<int>(task_future_int_type::task_status_type::kTimeout),
f.get_internal_promise().data());
1203 resume_pending_contexts({});
1206CASE_TEST(task_promise, then_empty_task) {
1207 task_future_int_type t;
1208 auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1211 CASE_MSG_INFO() <<
"thenable of empty task return int" << std::endl;
1219 resume_pending_contexts({});
1222CASE_TEST(task_promise, then_exiting_task) {
1223 auto t = task_func_await_int_simple();
1226 resume_pending_contexts({3000});
1228 auto f = t.then([](task_future_int_type::context_pointer_type ctx, task_future_int_type::value_type value) {
1230 static_cast<int>(task_future_int_type::task_status_type::kDone));
1232 CASE_MSG_INFO() <<
"thenable of exiting task return int" << std::endl;
1241CASE_TEST(task_promise, task_then_12_1_task_return_int_and_thenable_return_normal_int) {
1242 auto t = task_func_await_int_simple();
1244 [](task_future_int_type::context_pointer_type, task_future_int_type::value_type value) {
1246 CASE_MSG_INFO() <<
"first thenable return int" << std::endl;
1251 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1253 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1254 return value + ctx->get_private_data();
1262 resume_pending_contexts({2000});
1268CASE_TEST(task_promise, task_then_12_2_task_return_int_and_thenable_return_normal_void) {
1269 auto t = task_func_await_int_simple();
1271 [](
const task_future_int_type::context_pointer_type &, task_future_int_type::value_type value) {
1273 CASE_MSG_INFO() <<
"first thenable return void" << std::endl;
1277 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1279 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1287 resume_pending_contexts({2000});
1291CASE_TEST(task_promise, task_then_12_3_task_return_int_and_thenable_return_callable_int) {
1292 auto t = task_func_await_int_simple();
1294 [](task_future_int_type::context_pointer_type &&,
1295 task_future_int_type::value_type value) -> copp::callable_future<int> {
1297 CASE_MSG_INFO() <<
"first thenable return callable_future<int>" << std::endl;
1302 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1304 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1305 return value + ctx->get_private_data();
1313 resume_pending_contexts({2000});
1319CASE_TEST(task_promise, task_then_12_4_task_return_int_and_thenable_return_callable_void) {
1320 auto t = task_func_await_int_simple();
1322 [](
const task_future_int_type::context_pointer_type &,
1323 task_future_int_type::value_type value) -> copp::callable_future<void> {
1325 CASE_MSG_INFO() <<
"first thenable return callable_future<void>" << std::endl;
1330 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1332 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1340 resume_pending_contexts({2000});
1344CASE_TEST(task_promise, task_then_12_5_task_return_int_and_thenable_return_callable_int) {
1345 auto t = task_func_await_int_simple();
1347 [](task_future_int_type::context_pointer_type,
1348 task_future_int_type::value_type value) -> cotask::task_future<int, void> {
1350 CASE_MSG_INFO() <<
"first thenable return task_future<int>" << std::endl;
1355 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1357 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1358 return value + ctx->get_private_data();
1366 resume_pending_contexts({2000});
1372CASE_TEST(task_promise, task_then_12_6_task_return_int_and_thenable_return_callable_void) {
1373 auto t = task_func_await_int_simple();
1375 [](task_future_int_type::context_pointer_type &&,
1376 task_future_int_type::value_type value) -> cotask::task_future<void, void> {
1378 CASE_MSG_INFO() <<
"first thenable return task_future<void>" << std::endl;
1383 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1385 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1393 resume_pending_contexts({2000});
1397CASE_TEST(task_promise, task_then_12_7_task_return_void_and_thenable_return_normal_int) {
1398 auto t = task_func_await_void_simple();
1400 [](task_future_void_type::context_pointer_type) {
1401 CASE_MSG_INFO() <<
"first thenable return int" << std::endl;
1406 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1408 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1409 return value + ctx->get_private_data();
1417 resume_pending_contexts({});
1423CASE_TEST(task_promise, task_then_12_8_task_return_void_and_thenable_return_normal_void) {
1424 auto t = task_func_await_void_simple();
1426 [](
const task_future_void_type::context_pointer_type &) {
1427 CASE_MSG_INFO() <<
"first thenable return void" << std::endl;
1431 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1433 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1441 resume_pending_contexts({});
1445CASE_TEST(task_promise, task_then_12_9_task_return_void_and_thenable_return_callable_int) {
1446 auto t = task_func_await_void_simple();
1448 [](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
1449 CASE_MSG_INFO() <<
"first thenable return callable_future<int>" << std::endl;
1454 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1456 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1457 return value + ctx->get_private_data();
1465 resume_pending_contexts({});
1471CASE_TEST(task_promise, task_then_12_10_task_return_void_and_thenable_return_callable_void) {
1472 auto t = task_func_await_void_simple();
1474 [](
const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
1475 CASE_MSG_INFO() <<
"first thenable return callable_future<void>" << std::endl;
1480 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1482 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1490 resume_pending_contexts({});
1494CASE_TEST(task_promise, task_then_12_11_task_return_void_and_thenable_return_callable_int) {
1495 auto t = task_func_await_void_simple();
1497 [](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1498 CASE_MSG_INFO() <<
"first thenable return task_future<int>" << std::endl;
1503 [](cotask::task_future<int, int>::context_pointer_type ctx, task_future_int_type::value_type value) {
1505 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1506 return value + ctx->get_private_data();
1514 resume_pending_contexts({});
1520CASE_TEST(task_promise, task_then_12_12_task_return_void_and_thenable_return_callable_void) {
1521 auto t = task_func_await_void_simple();
1523 [](
const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1524 CASE_MSG_INFO() <<
"first thenable return task_future<void>" << std::endl;
1529 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1531 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1539 resume_pending_contexts({});
1544static cotask::task_future<int, void> task_func_some_any_all_callable_suspend() {
1545 auto suspend_callback = [](generator_future_int_type::context_pointer_type ctx) {
1546 ++g_task_future_suspend_generator_count;
1547 g_task_future_pending_int_contexts.push_back(ctx);
1549 auto resume_callback = [](
const generator_future_int_type::context_type &) {
1550 ++g_task_future_resume_generator_count;
1553 auto value =
co_await generator_future_int_type(suspend_callback, resume_callback);
1557static copp::callable_future<int> task_future_func_some_callable_in_container(
size_t expect_ready_count,
1558 copp::promise_status expect_status) {
1559 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1560 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1562 size_t resume_ready_count = 0;
1564 std::vector<cotask::task_future<int, void>> tasks;
1565 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1566 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1567 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1568 for (
auto &task_object : tasks) {
1569 task_object.start();
1572 copp::some_ready<cotask::task_future<int, void>>::type readys;
1573 auto some_result =
co_await copp::some(readys, 2, tasks);
1574 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(some_result));
1577 for (
auto &ready_task : readys) {
1578 if (ready_task->is_exiting()) {
1579 result += *ready_task->get_context()->data();
1580 ++resume_ready_count;
1587 some_result =
co_await copp::some(readys, 2, tasks);
1588 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(some_result));
1593 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1594 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1601CASE_TEST(task_promise, finish_some_in_container) {
1602 auto f = task_future_func_some_callable_in_container(2, copp::promise_status::kDone);
1607 resume_pending_contexts({471}, 1);
1609 resume_pending_contexts({473}, 1);
1614 resume_pending_contexts({});
1617CASE_TEST(task_promise, kill_some_in_container) {
1618 auto f = task_future_func_some_callable_in_container(0, copp::promise_status::kKilled);
1628 resume_pending_contexts({});
1631static copp::callable_future<int> task_future_func_some_callable_in_initialize_list(
1632 size_t expect_ready_count, copp::promise_status expect_status) {
1633 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1634 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1636 size_t resume_ready_count = 0;
1638 cotask::task_future<int, void> task1 = task_func_some_any_all_callable_suspend();
1639 cotask::task_future<int, void> task2 = task_func_some_any_all_callable_suspend();
1640 cotask::task_future<int, void> task3 = task_func_some_any_all_callable_suspend();
1645 copp::some_ready<cotask::task_future<int, void>>::type readys;
1646 std::reference_wrapper<cotask::task_future<int, void>> pending[] = {task1, task2, task3};
1647 auto some_result =
co_await copp::some(readys, 2, pending);
1648 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(some_result));
1651 for (
auto &ready_task : readys) {
1652 if (ready_task->is_exiting()) {
1653 result += *ready_task->get_context()->data();
1654 ++resume_ready_count;
1658 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1659 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1665CASE_TEST(task_promise, finish_some_in_initialize_list) {
1666 auto f = task_future_func_some_callable_in_initialize_list(2, copp::promise_status::kDone);
1671 resume_pending_contexts({471}, 1);
1673 resume_pending_contexts({473}, 1);
1678 resume_pending_contexts({});
1682static copp::callable_future<int> task_future_func_any_callable_in_container(
size_t expect_ready_count,
1683 copp::promise_status expect_status) {
1684 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1685 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1687 size_t resume_ready_count = 0;
1689 std::vector<cotask::task_future<int, void>> tasks;
1690 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1691 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1692 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1693 for (
auto &task_object : tasks) {
1694 task_object.start();
1697 copp::any_ready<cotask::task_future<int, void>>::type readys;
1698 auto any_result =
co_await copp::any(readys, tasks);
1699 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(any_result));
1702 for (
auto &ready_task : readys) {
1703 if (ready_task->is_exiting()) {
1704 result += *ready_task->get_context()->data();
1705 ++resume_ready_count;
1709 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1710 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1714 any_result =
co_await copp::any(readys, tasks);
1715 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(any_result));
1720 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1721 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1728CASE_TEST(task_promise, finish_any_in_container) {
1729 auto f = task_future_func_any_callable_in_container(1, copp::promise_status::kDone);
1734 resume_pending_contexts({671}, 1);
1739 resume_pending_contexts({});
1743static copp::callable_future<int> task_future_func_all_callable_in_container(
size_t expect_ready_count,
1744 copp::promise_status expect_status) {
1745 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1746 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1748 size_t resume_ready_count = 0;
1750 std::vector<cotask::task_future<int, void>> tasks;
1751 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1752 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1753 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1754 for (
auto &task_object : tasks) {
1755 task_object.start();
1758 copp::all_ready<cotask::task_future<int, void>>::type readys;
1759 auto all_result =
co_await copp::all(readys, tasks);
1760 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(all_result));
1763 for (
auto &ready_task : readys) {
1764 if (ready_task->is_exiting()) {
1765 result += *ready_task->get_context()->data();
1766 ++resume_ready_count;
1770 CASE_EXPECT_EQ(old_resume_generator_count + 3, g_task_future_resume_generator_count);
1771 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1775 all_result =
co_await copp::all(readys, tasks);
1776 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(all_result));
1781 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1782 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1789CASE_TEST(task_promise, finish_all_in_container) {
1790 auto f = task_future_func_all_callable_in_container(3, copp::promise_status::kDone);
1795 resume_pending_contexts({671}, 1);
1798 resume_pending_contexts({791, 793}, 2);
1803 resume_pending_contexts({});
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
#define CASE_EXPECT_FALSE(c)
#define CASE_EXPECT_EQ(l, r)
#define CASE_EXPECT_NE(l, r)
#define CASE_TEST(test_name, case_name)
#define CASE_EXPECT_TRUE(c)