16 #if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
19 struct task_future_private_data {
23 using task_future_int_type = cotask::task_future<int, task_future_private_data>;
24 using task_future_void_type = cotask::task_future<void, task_future_private_data>;
25 using task_future_int_type_no_private_data = cotask::task_future<int, void>;
26 using task_future_void_type_no_private_data = cotask::task_future<void, void>;
27 using callable_future_int_type = copp::callable_future<int>;
28 using callable_future_void_type = copp::callable_future<void>;
29 using generator_future_int_type = copp::generator_future<int>;
30 using generator_future_void_type = copp::generator_future<void>;
32 std::list<generator_future_int_type::context_pointer_type> g_task_future_pending_int_contexts;
33 std::list<generator_future_void_type::context_pointer_type> g_task_future_pending_void_contexts;
34 size_t g_task_future_resume_generator_count = 0;
35 size_t g_task_future_suspend_generator_count = 0;
37 static size_t resume_pending_contexts(std::list<int> values,
int max_count = 32767) {
39 while (max_count > 0 &&
40 (!g_task_future_pending_int_contexts.empty() || !g_task_future_pending_void_contexts.empty())) {
42 if (!g_task_future_pending_int_contexts.empty()) {
43 auto ctx = *g_task_future_pending_int_contexts.begin();
44 g_task_future_pending_int_contexts.pop_front();
46 if (!values.empty()) {
47 int val = values.front();
57 if (!g_task_future_pending_void_contexts.empty()) {
58 auto ctx = *g_task_future_pending_void_contexts.begin();
59 g_task_future_pending_void_contexts.pop_front();
69 static void generator_int_suspend_callback(generator_future_int_type::context_pointer_type ctx) {
70 ++g_task_future_suspend_generator_count;
71 g_task_future_pending_int_contexts.push_back(ctx);
73 static void generator_int_resume_callback(
const generator_future_int_type::context_type &) {
74 ++g_task_future_resume_generator_count;
77 static callable_future_int_type task_future_func_int_l1(
int inout) {
78 CASE_MSG_INFO() <<
"callable inner future ready int: " << inout << std::endl;
82 static callable_future_int_type task_future_func_int_l2(
int inout) {
83 generator_future_int_type generator{generator_int_suspend_callback, generator_int_resume_callback};
84 auto gen_res = co_await generator;
88 co_return inout + gen_res;
91 static callable_future_int_type task_future_func_await_int() {
92 auto v = task_future_func_int_l1(3);
93 auto u = task_future_func_int_l2(11);
94 int x = (co_await v + co_await u);
98 static task_future_int_type task_func_await_int() {
99 auto current_status = co_yield task_future_void_type::yield_status();
100 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
101 auto private_data = co_yield task_future_int_type::yield_private_data();
102 private_data->data = 121000;
105 auto v = task_future_func_await_int();
111 static callable_future_int_type task_future_func_no_wait_int() {
112 auto v = task_future_func_int_l1(7);
113 auto u = task_future_func_int_l1(19);
114 int x = (co_await v + co_await u);
118 static task_future_int_type task_func_no_wait_int() {
119 auto current_status = co_yield task_future_void_type::yield_status();
120 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
121 auto private_data = co_yield cotask::task_private_data<task_future_private_data>();
122 private_data->data = 121000;
125 auto v = task_future_func_no_wait_int();
131 static void generator_void_suspend_callback(generator_future_void_type::context_pointer_type ctx) {
132 ++g_task_future_suspend_generator_count;
133 g_task_future_pending_void_contexts.push_back(ctx);
135 static void generator_void_resume_callback(
const generator_future_void_type::context_type &) {
136 ++g_task_future_resume_generator_count;
139 static callable_future_void_type task_future_func_void_l1() {
140 CASE_MSG_INFO() <<
"callable inner future ready void" << std::endl;
144 static callable_future_void_type task_future_func_void_l2() {
145 generator_future_void_type generator{generator_void_suspend_callback, generator_void_resume_callback};
150 static callable_future_void_type task_future_func_await_void() {
151 auto v = task_future_func_void_l1();
152 auto u = task_future_func_void_l2();
158 static task_future_void_type task_func_await_void() {
159 auto current_status = co_yield task_future_void_type::yield_status();
160 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
161 auto private_data = co_yield task_future_void_type::yield_private_data();
162 private_data->data = 123000;
165 auto v = task_future_func_await_void();
171 static callable_future_void_type task_future_func_no_wait_void() {
172 auto v = task_future_func_void_l1();
173 auto u = task_future_func_void_l1();
179 static task_future_void_type task_func_no_wait_void() {
180 auto current_status = co_yield task_future_void_type::yield_status();
181 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(current_status));
182 auto private_data = co_yield cotask::task_private_data<task_future_private_data>();
183 private_data->data = 123000;
186 auto v = task_future_func_no_wait_void();
192 static task_future_void_type_no_private_data task_func_await_pick_task_id(
193 task_future_void_type_no_private_data::id_type &output) {
194 output = co_yield task_future_void_type_no_private_data::yield_task_id();
201 CASE_TEST(task_promise, task_future_void_yield_task_id) {
202 task_future_void_type_no_private_data::id_type task_id = 0;
203 task_future_void_type_no_private_data t = task_func_await_pick_task_id(task_id);
215 CASE_TEST(task_promise, task_future_integer_need_resume) {
216 size_t old_resume_generator_count = g_task_future_resume_generator_count;
217 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
219 task_future_int_type t = task_func_await_int();
220 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
229 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
236 resume_pending_contexts({100});
237 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
245 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
246 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
249 CASE_TEST(task_promise, task_future_void_need_resume) {
250 size_t old_resume_generator_count = g_task_future_resume_generator_count;
251 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
253 task_future_void_type t = task_func_await_void();
254 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
263 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
270 resume_pending_contexts({100});
271 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
278 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
279 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
282 CASE_TEST(task_promise, task_future_integer_no_resume) {
283 size_t old_resume_generator_count = g_task_future_resume_generator_count;
284 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
286 task_future_int_type t = task_func_no_wait_int();
287 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
296 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
304 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
305 CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
308 CASE_TEST(task_promise, task_future_void_no_resume) {
309 size_t old_resume_generator_count = g_task_future_resume_generator_count;
310 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
312 task_future_void_type t = task_func_no_wait_void();
313 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
322 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
329 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
330 CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
334 static task_future_int_type task_func_await_int_generator() {
335 generator_future_int_type generator{generator_int_suspend_callback, generator_int_resume_callback};
336 auto res = co_await generator;
340 static callable_future_int_type task_future_func_await_int_task() {
341 task_future_int_type t = task_func_await_int_generator();
343 auto res = co_await t;
347 static task_future_int_type task_func_await_int_task() {
348 task_future_int_type t = task_func_await_int_generator();
350 auto res = co_await t;
355 CASE_TEST(task_promise, callable_future_await_task) {
356 size_t old_resume_generator_count = g_task_future_resume_generator_count;
357 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
359 callable_future_int_type f = task_future_func_await_int_task();
360 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(f.get_status()));
364 resume_pending_contexts({1000});
365 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(f.get_status()));
369 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
370 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
373 CASE_TEST(task_promise, task_future_await_task) {
374 size_t old_resume_generator_count = g_task_future_resume_generator_count;
375 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
377 task_future_int_type t = task_func_await_int_task();
378 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
386 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
393 resume_pending_contexts({2000});
394 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(t.get_status()));
402 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
403 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
407 static callable_future_int_type task_func_await_callable_and_be_killed() {
408 auto u = task_future_func_int_l2(13);
413 static task_future_int_type task_func_await_and_be_killed_by_caller() {
414 auto v = task_func_await_callable_and_be_killed();
419 std::shared_ptr<task_future_int_type> g_task_promise_killed_by_callee;
420 static task_future_int_type task_func_await_and_be_killed_by_callee(task_future_int_type::task_status_type status) {
421 g_task_promise_killed_by_callee->kill(status);
422 auto v = task_func_await_callable_and_be_killed();
430 CASE_TEST(task_promise, killed_by_caller) {
431 size_t old_resume_generator_count = g_task_future_resume_generator_count;
432 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
434 task_future_int_type t = task_func_await_and_be_killed_by_caller();
435 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
443 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
451 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kKilled),
static_cast<int>(t.get_status()));
457 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
459 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
460 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
462 resume_pending_contexts({100});
463 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
470 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
471 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
474 CASE_TEST(task_promise, killed_by_callee) {
475 size_t old_resume_generator_count = g_task_future_resume_generator_count;
476 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
478 task_future_int_type t = task_func_await_and_be_killed_by_callee(copp::promise_status::kKilled);
479 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
486 g_task_promise_killed_by_callee = std::make_shared<task_future_int_type>(t);
488 g_task_promise_killed_by_callee.reset();
490 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kKilled),
static_cast<int>(t.get_status()));
496 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
498 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
499 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
501 resume_pending_contexts({100});
502 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *t.get_context()->data());
509 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
510 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
514 CASE_TEST(task_promise, cancel_by_caller) {
515 size_t old_resume_generator_count = g_task_future_resume_generator_count;
516 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
518 task_future_int_type t = task_func_await_and_be_killed_by_caller();
519 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
527 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
535 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCancle),
static_cast<int>(t.get_status()));
541 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kCancle), *t.get_context()->data());
543 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
544 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
546 resume_pending_contexts({100});
547 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kCancle), *t.get_context()->data());
554 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
555 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
559 CASE_TEST(task_promise, timeout_by_caller) {
560 size_t old_resume_generator_count = g_task_future_resume_generator_count;
561 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
563 task_future_int_type t = task_func_await_and_be_killed_by_caller();
564 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
572 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(t.get_status()));
580 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kTimeout),
static_cast<int>(t.get_status()));
586 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
588 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
589 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
591 resume_pending_contexts({100});
592 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
599 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
600 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
603 CASE_TEST(task_promise, timeout_by_callee) {
604 size_t old_resume_generator_count = g_task_future_resume_generator_count;
605 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
607 task_future_int_type t = task_func_await_and_be_killed_by_callee(copp::promise_status::kTimeout);
608 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(t.get_status()));
615 g_task_promise_killed_by_callee = std::make_shared<task_future_int_type>(t);
617 g_task_promise_killed_by_callee.reset();
619 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kTimeout),
static_cast<int>(t.get_status()));
625 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
627 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
628 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
630 resume_pending_contexts({100});
631 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *t.get_context()->data());
638 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
639 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
643 static task_future_int_type task_func_await_child_task_child() {
644 auto u = task_future_func_int_l2(53);
649 static task_future_int_type task_func_await_child_task_parent(task_future_int_type &out) {
650 out = task_func_await_child_task_child();
651 int x = co_await out;
655 static task_future_int_type task_func_await_empty() {
656 task_future_int_type empty;
657 int x = co_await empty;
664 CASE_TEST(task_promise, kill_parent_only) {
665 size_t old_resume_generator_count = g_task_future_resume_generator_count;
666 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
668 task_future_int_type child;
669 task_future_int_type parent = task_func_await_child_task_parent(child);
670 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(parent.get_status()));
678 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(parent.get_status()));
685 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kCreated),
static_cast<int>(child.get_status()));
686 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
687 CASE_EXPECT_EQ(old_suspend_generator_count, g_task_future_suspend_generator_count);
689 CASE_EXPECT_EQ(old_resume_generator_count, g_task_future_resume_generator_count);
690 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
692 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(child.get_status()));
699 CASE_EXPECT_TRUE(parent.kill(task_future_int_type::task_status_type::kTimeout));
700 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kTimeout),
static_cast<int>(parent.get_status()));
706 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *parent.get_context()->data());
708 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kRunning),
static_cast<int>(child.get_status()));
715 resume_pending_contexts({1000});
716 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kTimeout), *parent.get_context()->data());
723 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kDone),
static_cast<int>(child.get_status()));
731 CASE_EXPECT_EQ(old_resume_generator_count + 1, g_task_future_resume_generator_count);
732 CASE_EXPECT_EQ(old_suspend_generator_count + 1, g_task_future_suspend_generator_count);
736 task_future_int_type t = task_func_await_empty();
739 task_future_int_type empty;
743 CASE_EXPECT_EQ(
static_cast<int>(copp::promise_status::kInvalid),
static_cast<int>(empty.get_status()));
751 CASE_TEST(task_promise, task_destroy_and_auto_resume) {
752 task_future_int_type parent;
754 task_future_int_type child;
755 parent = task_func_await_child_task_parent(child);
765 task_future_int_type move_child_assign = std::move(child);
773 task_future_int_type move_child_ctor{std::move(move_child_assign)};
777 task_future_int_type copy_child_assign = move_child_ctor;
778 task_future_int_type copy_child_ctor{move_child_ctor};
784 CASE_EXPECT_EQ(copy_child_assign.get_context(), copy_child_ctor.get_context());
785 CASE_EXPECT_EQ(copy_child_assign.get_context(), move_child_ctor.get_context());
787 CASE_EXPECT_EQ(copy_child_assign.get_id(), copy_child_ctor.get_id());
788 CASE_EXPECT_EQ(copy_child_assign.get_id(), move_child_ctor.get_id());
796 CASE_EXPECT_EQ(-
static_cast<int>(copp::promise_status::kKilled), *parent.get_context()->data());
798 resume_pending_contexts({});
802 static task_future_int_type task_func_await_int_simple() {
803 auto u = task_future_func_int_l2(91);
808 static task_future_void_type task_func_await_void_simple() {
809 auto u = task_future_func_void_l2();
814 static callable_future_int_type task_func_callable_await_task_int_simple() {
815 auto u = task_func_await_int_simple();
823 CASE_TEST(task_promise, forget_to_start) {
825 {
auto f = task_func_callable_await_task_int_simple(); }
827 resume_pending_contexts({});
830 CASE_TEST(task_promise, callable_then_12_1_task_return_int_and_thenable_return_normal_int) {
831 auto t = task_func_await_int_simple();
842 resume_pending_contexts({2000});
848 CASE_TEST(task_promise, callable_then_12_2_task_return_int_and_thenable_return_normal_void) {
849 auto t = task_func_await_int_simple();
859 resume_pending_contexts({2000});
863 CASE_TEST(task_promise, callable_then_12_3_task_return_int_and_thenable_return_callable_int) {
864 auto t = task_func_await_int_simple();
865 auto f = t.then([](task_future_int_type::context_pointer_type &&,
868 CASE_MSG_INFO() <<
"thenable return callable_future<int>" << std::endl;
876 resume_pending_contexts({2000});
882 CASE_TEST(task_promise, callable_then_12_4_task_return_int_and_thenable_return_callable_void) {
883 auto t = task_func_await_int_simple();
884 auto f = t.then([](
const task_future_int_type::context_pointer_type &,
887 CASE_MSG_INFO() <<
"thenable return callable_future<void>" << std::endl;
895 resume_pending_contexts({2000});
899 CASE_TEST(task_promise, callable_then_12_5_task_return_int_and_thenable_return_callable_int) {
900 auto t = task_func_await_int_simple();
901 auto f = t.then([](task_future_int_type::context_pointer_type,
904 CASE_MSG_INFO() <<
"thenable return task_future<int>" << std::endl;
912 resume_pending_contexts({2000});
918 CASE_TEST(task_promise, callable_then_12_6_task_return_int_and_thenable_return_callable_void) {
919 auto t = task_func_await_int_simple();
920 auto f = t.then([](task_future_int_type::context_pointer_type &&,
923 CASE_MSG_INFO() <<
"thenable return task_future<void>" << std::endl;
931 resume_pending_contexts({2000});
935 CASE_TEST(task_promise, callable_then_12_7_task_return_void_and_thenable_return_normal_int) {
936 auto t = task_func_await_void_simple();
937 auto f = t.then([](task_future_void_type::context_pointer_type) {
946 resume_pending_contexts({});
952 CASE_TEST(task_promise, callable_then_12_8_task_return_void_and_thenable_return_normal_void) {
953 auto t = task_func_await_void_simple();
954 auto f = t.then([](
const task_future_void_type::context_pointer_type &) {
962 resume_pending_contexts({});
966 CASE_TEST(task_promise, callable_then_12_9_task_return_void_and_thenable_return_callable_int) {
967 auto t = task_func_await_void_simple();
968 auto f = t.then([](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
969 CASE_MSG_INFO() <<
"thenable return callable_future<int>" << std::endl;
977 resume_pending_contexts({});
983 CASE_TEST(task_promise, callable_then_12_10_task_return_void_and_thenable_return_callable_void) {
984 auto t = task_func_await_void_simple();
985 auto f = t.then([](
const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
986 CASE_MSG_INFO() <<
"thenable return callable_future<void>" << std::endl;
994 resume_pending_contexts({});
998 CASE_TEST(task_promise, callable_then_12_11_task_return_void_and_thenable_return_callable_int) {
999 auto t = task_func_await_void_simple();
1000 auto f = t.then([](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1001 CASE_MSG_INFO() <<
"thenable return task_future<int>" << std::endl;
1009 resume_pending_contexts({});
1015 CASE_TEST(task_promise, callable_then_12_12_task_return_void_and_thenable_return_callable_void) {
1016 auto t = task_func_await_void_simple();
1017 auto f = t.then([](
const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1018 CASE_MSG_INFO() <<
"thenable return task_future<void>" << std::endl;
1026 resume_pending_contexts({});
1030 CASE_TEST(task_promise, then_kill_task) {
1031 auto t = task_func_await_int_simple();
1034 static_cast<int>(task_future_int_type::task_status_type::kTimeout));
1035 CASE_EXPECT_EQ(-
static_cast<int>(task_future_int_type::task_status_type::kTimeout), value);
1036 CASE_MSG_INFO() <<
"thenable of timeout task return int" << std::endl;
1044 t.kill(task_future_int_type::task_status_type::kTimeout);
1047 CASE_EXPECT_EQ(-
static_cast<int>(task_future_int_type::task_status_type::kTimeout), f.get_internal_promise().data());
1049 resume_pending_contexts({});
1052 CASE_TEST(task_promise, then_empty_task) {
1053 task_future_int_type t;
1057 CASE_MSG_INFO() <<
"thenable of empty task return int" << std::endl;
1065 resume_pending_contexts({});
1068 CASE_TEST(task_promise, then_exiting_task) {
1069 auto t = task_func_await_int_simple();
1072 resume_pending_contexts({3000});
1076 static_cast<int>(task_future_int_type::task_status_type::kDone));
1078 CASE_MSG_INFO() <<
"thenable of exiting task return int" << std::endl;
1087 CASE_TEST(task_promise, task_then_12_1_task_return_int_and_thenable_return_normal_int) {
1088 auto t = task_func_await_int_simple();
1092 CASE_MSG_INFO() <<
"first thenable return int" << std::endl;
1099 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1100 return value + ctx->get_private_data();
1108 resume_pending_contexts({2000});
1114 CASE_TEST(task_promise, task_then_12_2_task_return_int_and_thenable_return_normal_void) {
1115 auto t = task_func_await_int_simple();
1119 CASE_MSG_INFO() <<
"first thenable return void" << std::endl;
1123 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1125 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1133 resume_pending_contexts({2000});
1137 CASE_TEST(task_promise, task_then_12_3_task_return_int_and_thenable_return_callable_int) {
1138 auto t = task_func_await_int_simple();
1140 [](task_future_int_type::context_pointer_type &&,
1143 CASE_MSG_INFO() <<
"first thenable return callable_future<int>" << std::endl;
1150 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1151 return value + ctx->get_private_data();
1159 resume_pending_contexts({2000});
1165 CASE_TEST(task_promise, task_then_12_4_task_return_int_and_thenable_return_callable_void) {
1166 auto t = task_func_await_int_simple();
1168 [](
const task_future_int_type::context_pointer_type &,
1171 CASE_MSG_INFO() <<
"first thenable return callable_future<void>" << std::endl;
1176 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1178 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1186 resume_pending_contexts({2000});
1190 CASE_TEST(task_promise, task_then_12_5_task_return_int_and_thenable_return_callable_int) {
1191 auto t = task_func_await_int_simple();
1193 [](task_future_int_type::context_pointer_type,
1196 CASE_MSG_INFO() <<
"first thenable return task_future<int>" << std::endl;
1203 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1204 return value + ctx->get_private_data();
1212 resume_pending_contexts({2000});
1218 CASE_TEST(task_promise, task_then_12_6_task_return_int_and_thenable_return_callable_void) {
1219 auto t = task_func_await_int_simple();
1221 [](task_future_int_type::context_pointer_type &&,
1224 CASE_MSG_INFO() <<
"first thenable return task_future<void>" << std::endl;
1229 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1231 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1239 resume_pending_contexts({2000});
1243 CASE_TEST(task_promise, task_then_12_7_task_return_void_and_thenable_return_normal_int) {
1244 auto t = task_func_await_void_simple();
1246 [](task_future_void_type::context_pointer_type) {
1247 CASE_MSG_INFO() <<
"first thenable return int" << std::endl;
1254 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1255 return value + ctx->get_private_data();
1263 resume_pending_contexts({});
1269 CASE_TEST(task_promise, task_then_12_8_task_return_void_and_thenable_return_normal_void) {
1270 auto t = task_func_await_void_simple();
1272 [](
const task_future_void_type::context_pointer_type &) {
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({});
1291 CASE_TEST(task_promise, task_then_12_9_task_return_void_and_thenable_return_callable_int) {
1292 auto t = task_func_await_void_simple();
1294 [](task_future_void_type::context_pointer_type) -> copp::callable_future<int> {
1295 CASE_MSG_INFO() <<
"first thenable return callable_future<int>" << std::endl;
1302 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1303 return value + ctx->get_private_data();
1311 resume_pending_contexts({});
1317 CASE_TEST(task_promise, task_then_12_10_task_return_void_and_thenable_return_callable_void) {
1318 auto t = task_func_await_void_simple();
1320 [](
const task_future_void_type::context_pointer_type &) -> copp::callable_future<void> {
1321 CASE_MSG_INFO() <<
"first thenable return callable_future<void>" << std::endl;
1326 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1328 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1336 resume_pending_contexts({});
1340 CASE_TEST(task_promise, task_then_12_11_task_return_void_and_thenable_return_callable_int) {
1341 auto t = task_func_await_void_simple();
1343 [](task_future_void_type::context_pointer_type) -> cotask::task_future<int, void> {
1344 CASE_MSG_INFO() <<
"first thenable return task_future<int>" << std::endl;
1351 CASE_MSG_INFO() <<
"second thenable return int" << std::endl;
1352 return value + ctx->get_private_data();
1360 resume_pending_contexts({});
1366 CASE_TEST(task_promise, task_then_12_12_task_return_void_and_thenable_return_callable_void) {
1367 auto t = task_func_await_void_simple();
1369 [](
const task_future_void_type::context_pointer_type &) -> cotask::task_future<void, void> {
1370 CASE_MSG_INFO() <<
"first thenable return task_future<void>" << std::endl;
1375 [](cotask::task_future<void, int>::context_pointer_type ctx) {
1377 CASE_MSG_INFO() <<
"second thenable return void" << std::endl;
1385 resume_pending_contexts({});
1390 static cotask::task_future<int, void> task_func_some_any_all_callable_suspend() {
1391 auto suspend_callback = [](generator_future_int_type::context_pointer_type ctx) {
1392 ++g_task_future_suspend_generator_count;
1393 g_task_future_pending_int_contexts.push_back(ctx);
1395 auto resume_callback = [](
const generator_future_int_type::context_type &) {
1396 ++g_task_future_resume_generator_count;
1399 auto value = co_await generator_future_int_type(suspend_callback, resume_callback);
1403 static copp::callable_future<int> task_future_func_some_callable_in_container(
size_t expect_ready_count,
1404 copp::promise_status expect_status) {
1405 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1406 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1408 size_t resume_ready_count = 0;
1410 std::vector<cotask::task_future<int, void>> tasks;
1411 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1412 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1413 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1414 for (
auto &task_object : tasks) {
1415 task_object.start();
1418 copp::some_ready<cotask::task_future<int, void>>::type readys;
1419 auto some_result = co_await copp::some(readys, 2, tasks);
1420 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(some_result));
1423 for (
auto &ready_task : readys) {
1424 if (ready_task->is_exiting()) {
1425 result += *ready_task->get_context()->data();
1426 ++resume_ready_count;
1433 some_result = co_await copp::some(readys, 2, tasks);
1434 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(some_result));
1439 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1440 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1447 CASE_TEST(task_promise, finish_some_in_container) {
1448 auto f = task_future_func_some_callable_in_container(2, copp::promise_status::kDone);
1453 resume_pending_contexts({471}, 1);
1455 resume_pending_contexts({473}, 1);
1460 resume_pending_contexts({});
1463 CASE_TEST(task_promise, kill_some_in_container) {
1464 auto f = task_future_func_some_callable_in_container(0, copp::promise_status::kKilled);
1474 resume_pending_contexts({});
1477 static copp::callable_future<int> task_future_func_some_callable_in_initialize_list(
1478 size_t expect_ready_count, copp::promise_status expect_status) {
1479 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1480 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1482 size_t resume_ready_count = 0;
1484 cotask::task_future<int, void> task1 = task_func_some_any_all_callable_suspend();
1485 cotask::task_future<int, void> task2 = task_func_some_any_all_callable_suspend();
1486 cotask::task_future<int, void> task3 = task_func_some_any_all_callable_suspend();
1491 copp::some_ready<cotask::task_future<int, void>>::type readys;
1492 std::reference_wrapper<cotask::task_future<int, void>> pending[] = {task1, task2, task3};
1493 auto some_result = co_await copp::some(readys, 2, pending);
1494 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(some_result));
1497 for (
auto &ready_task : readys) {
1498 if (ready_task->is_exiting()) {
1499 result += *ready_task->get_context()->data();
1500 ++resume_ready_count;
1504 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1505 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1511 CASE_TEST(task_promise, finish_some_in_initialize_list) {
1512 auto f = task_future_func_some_callable_in_initialize_list(2, copp::promise_status::kDone);
1517 resume_pending_contexts({471}, 1);
1519 resume_pending_contexts({473}, 1);
1524 resume_pending_contexts({});
1528 static copp::callable_future<int> task_future_func_any_callable_in_container(
size_t expect_ready_count,
1529 copp::promise_status expect_status) {
1530 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1531 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1533 size_t resume_ready_count = 0;
1535 std::vector<cotask::task_future<int, void>> tasks;
1536 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1537 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1538 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1539 for (
auto &task_object : tasks) {
1540 task_object.start();
1543 copp::any_ready<cotask::task_future<int, void>>::type readys;
1544 auto any_result = co_await copp::any(readys, tasks);
1545 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(any_result));
1548 for (
auto &ready_task : readys) {
1549 if (ready_task->is_exiting()) {
1550 result += *ready_task->get_context()->data();
1551 ++resume_ready_count;
1555 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1556 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1560 any_result = co_await copp::any(readys, tasks);
1561 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(any_result));
1566 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1567 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1574 CASE_TEST(task_promise, finish_any_in_container) {
1575 auto f = task_future_func_any_callable_in_container(1, copp::promise_status::kDone);
1580 resume_pending_contexts({671}, 1);
1585 resume_pending_contexts({});
1589 static copp::callable_future<int> task_future_func_all_callable_in_container(
size_t expect_ready_count,
1590 copp::promise_status expect_status) {
1591 size_t old_resume_generator_count = g_task_future_resume_generator_count;
1592 size_t old_suspend_generator_count = g_task_future_suspend_generator_count;
1594 size_t resume_ready_count = 0;
1596 std::vector<cotask::task_future<int, void>> tasks;
1597 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1598 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1599 tasks.emplace_back(task_func_some_any_all_callable_suspend());
1600 for (
auto &task_object : tasks) {
1601 task_object.start();
1604 copp::all_ready<cotask::task_future<int, void>>::type readys;
1605 auto all_result = co_await copp::all(readys, tasks);
1606 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(all_result));
1609 for (
auto &ready_task : readys) {
1610 if (ready_task->is_exiting()) {
1611 result += *ready_task->get_context()->data();
1612 ++resume_ready_count;
1616 CASE_EXPECT_EQ(old_resume_generator_count + 3, g_task_future_resume_generator_count);
1617 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1621 all_result = co_await copp::all(readys, tasks);
1622 CASE_EXPECT_EQ(
static_cast<int>(expect_status),
static_cast<int>(all_result));
1627 CASE_EXPECT_EQ(old_resume_generator_count + expect_ready_count, g_task_future_resume_generator_count);
1628 CASE_EXPECT_EQ(old_suspend_generator_count + 3, g_task_future_suspend_generator_count);
1635 CASE_TEST(task_promise, finish_all_in_container) {
1636 auto f = task_future_func_all_callable_in_container(3, copp::promise_status::kDone);
1641 resume_pending_contexts({671}, 1);
1644 resume_pending_contexts({791, 793}, 2);
1649 resume_pending_contexts({});
constexpr auto data(TCONTAINER &&container) -> decltype(container.data())
std::shared_ptr< cli::cmd_option_value > value_type
CASE_TEST(task_promise, disabled)
#define CASE_EXPECT_FALSE(c)
#define CASE_EXPECT_EQ(l, r)
#define CASE_EXPECT_NE(l, r)
#define CASE_EXPECT_TRUE(c)