15 #if defined(LIBCOTASK_MACRO_ENABLED) && defined(LIBCOPP_MACRO_ENABLE_WIN_FIBER) && LIBCOPP_MACRO_ENABLE_WIN_FIBER
16 struct test_context_task_fiber_default_test_macro {
17 using stack_allocator_type = copp::allocator::stack_allocator_malloc;
18 using coroutine_type = copp::coroutine_context_fiber_container<stack_allocator_type>;
22 static int g_test_coroutine_task_fiber_status = 0;
23 static int g_test_coroutine_task_fiber_on_finished = 0;
24 class test_context_task_fiber_action_base :
public cotask::impl::task_action_impl {
27 virtual int operator()() = 0;
29 int operator()(
void *priv_data) {
30 ++g_test_coroutine_task_fiber_status;
40 ++g_test_coroutine_task_fiber_status;
45 virtual int on_finished(cotask::impl::task_impl &) {
46 ++g_test_coroutine_task_fiber_on_finished;
51 class test_context_task_fiber_action :
public test_context_task_fiber_action_base {
53 using test_context_task_fiber_action_base::operator();
56 virtual int operator()() {
return 0; }
59 CASE_TEST(coroutine_task_fiber, custom_action) {
60 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
61 g_test_coroutine_task_fiber_status = 0;
62 g_test_coroutine_task_fiber_on_finished = 0;
66 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_action());
67 task_ptr_type co_another_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
68 test_context_task_fiber_action());
73 CASE_EXPECT_EQ(0, co_task->start(&g_test_coroutine_task_fiber_status));
80 CASE_EXPECT_EQ(0, co_another_task->start(&g_test_coroutine_task_fiber_status));
100 ++g_test_coroutine_task_fiber_status;
109 struct test_context_task_fiber_functor {
111 int operator()(
void *)
const {
112 ++g_test_coroutine_task_fiber_status;
117 ++g_test_coroutine_task_fiber_status;
124 CASE_TEST(coroutine_task_fiber, functor_action) {
125 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
127 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_functor());
128 g_test_coroutine_task_fiber_status = 0;
132 ++g_test_coroutine_task_fiber_status;
140 ++g_test_coroutine_task_fiber_status;
146 static int test_context_task_fiber_function_1(
void *) {
147 ++g_test_coroutine_task_fiber_status;
152 ++g_test_coroutine_task_fiber_status;
158 static void test_context_task_fiber_function_2(
void *) {
159 ++g_test_coroutine_task_fiber_status;
164 ++g_test_coroutine_task_fiber_status;
168 CASE_TEST(coroutine_task_fiber, function_action) {
170 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
172 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_1);
173 g_test_coroutine_task_fiber_status = 0;
177 ++g_test_coroutine_task_fiber_status;
185 ++g_test_coroutine_task_fiber_status;
187 CASE_EXPECT_EQ(co_task->get_coroutine_context()->get_ret_code(), 100);
191 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
193 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_2);
194 g_test_coroutine_task_fiber_status = 0;
198 ++g_test_coroutine_task_fiber_status;
206 ++g_test_coroutine_task_fiber_status;
211 CASE_TEST(coroutine_task_fiber, cancel) {
212 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
214 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_1);
215 g_test_coroutine_task_fiber_status = 0;
219 ++g_test_coroutine_task_fiber_status;
229 static void test_context_task_fiber_function_3(
void *) {
230 ++g_test_coroutine_task_fiber_status;
240 ++g_test_coroutine_task_fiber_status;
244 CASE_TEST(coroutine_task_fiber, coroutine_context_yield) {
245 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
247 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_3);
248 g_test_coroutine_task_fiber_status = 0;
252 ++g_test_coroutine_task_fiber_status;
261 ++g_test_coroutine_task_fiber_status;
267 struct test_context_task_fiber_mem_function {
268 cotask::task<test_context_task_fiber_default_test_macro>::id_t task_id_;
270 int real_run(
void *) {
271 ++g_test_coroutine_task_fiber_status;
274 CASE_EXPECT_EQ(task_id_, cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_id());
275 cotask::task<test_context_task_fiber_default_test_macro>::this_task()->yield();
276 CASE_EXPECT_EQ(task_id_, cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_id());
278 ++g_test_coroutine_task_fiber_status;
285 CASE_TEST(coroutine_task_fiber, mem_function_action) {
286 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
287 test_context_task_fiber_mem_function obj;
288 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
289 &test_context_task_fiber_mem_function::real_run, &obj);
290 g_test_coroutine_task_fiber_status = 0;
291 obj.task_id_ = co_task->get_id();
295 ++g_test_coroutine_task_fiber_status;
303 ++g_test_coroutine_task_fiber_status;
306 CASE_EXPECT_NE(co_task->get_coroutine_context()->get_ret_code(), -1);
309 CASE_TEST(coroutine_task_fiber, auto_finish) {
310 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
312 test_context_task_fiber_mem_function obj;
313 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
314 &test_context_task_fiber_mem_function::real_run, &obj);
315 g_test_coroutine_task_fiber_status = 0;
316 obj.task_id_ = co_task->get_id();
321 test_context_task_fiber_mem_function obj;
322 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
323 &test_context_task_fiber_mem_function::real_run, &obj);
324 g_test_coroutine_task_fiber_status = 0;
325 obj.task_id_ = co_task->get_id();
329 ++g_test_coroutine_task_fiber_status;
335 ++g_test_coroutine_task_fiber_status;
339 struct test_context_task_fiber_next_action :
public cotask::impl::task_action_impl {
342 test_context_task_fiber_next_action(
int s,
int c) : cotask::
impl::task_action_impl(), set_(s), check_(c) {}
344 int operator()(
void *) {
346 g_test_coroutine_task_fiber_status = set_;
350 ++g_test_coroutine_task_fiber_on_finished;
356 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
359 g_test_coroutine_task_fiber_status = 0;
362 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_next_action(15, 0));
363 co_task->next(test_context_task_fiber_next_action(7, 15))
364 ->next(test_context_task_fiber_next_action(99, 7))
365 ->next(test_context_task_fiber_next_action(1023, 99))
366 ->next(test_context_task_fiber_next_action(5, 1023));
376 g_test_coroutine_task_fiber_status = 0;
378 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_next_action(2, 1));
380 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_function_1);
383 co_task_a->next(co_task_b);
391 struct test_context_task_fiber_functor_drived :
public cotask::impl::task_action_impl {
395 test_context_task_fiber_functor_drived(
int a,
int b) : a_(a), b_(b) {}
397 virtual int operator()(
void *) {
405 CASE_TEST(coroutine_task_fiber, functor_drived_action) {
406 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
407 cotask::task<test_context_task_fiber_default_test_macro>::coroutine_type::allocator_type alloc;
409 cotask::task<test_context_task_fiber_default_test_macro>::create_with<test_context_task_fiber_functor_drived>(
414 static int test_context_task_fiber_priavte_buffer(
void *) {
415 void *priv_data = cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_private_buffer();
416 size_t priv_sz = cotask::task<test_context_task_fiber_default_test_macro>::this_task()->get_private_buffer_size();
420 if (priv_sz >= 256) {
421 char checked_data[256];
422 memset(checked_data, 0x5e, 256);
430 CASE_TEST(coroutine_task_fiber, priavte_buffer) {
431 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
432 task_ptr_type co_task = cotask::task<test_context_task_fiber_default_test_macro>::create(
433 test_context_task_fiber_priavte_buffer, 16384, 256);
435 void *priv_data = co_task->get_private_buffer();
436 memset(priv_data, 0x5e, 256);
441 static int test_context_task_fiber_timeout(
void *) {
442 cotask::task<test_context_task_fiber_default_test_macro>::this_task()->yield();
444 CASE_EXPECT_TRUE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_timeout());
445 CASE_EXPECT_TRUE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_faulted());
446 CASE_EXPECT_FALSE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_completed());
447 CASE_EXPECT_TRUE(cotask::task<test_context_task_fiber_default_test_macro>::this_task()->is_exiting());
452 CASE_TEST(coroutine_task_fiber, kill_and_timeout) {
453 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
455 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_timeout, 16384, 256);
457 void *priv_data = co_task->get_private_buffer();
458 memset(priv_data, 0x5e, 256);
474 static int test_context_task_fiber_await_1(
void *) {
475 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
477 task_ptr_type self = cotask::task<test_context_task_fiber_default_test_macro>::this_task();
482 void *priv_data =
self->get_private_buffer();
483 cotask::task<test_context_task_fiber_default_test_macro>::self_t *other_task =
484 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data);
486 if (other_task->is_exiting()) {
489 if (self->is_exiting()) {
499 static int test_context_task_fiber_await_2(
void *) {
return 0; }
501 CASE_TEST(coroutine_task_fiber, await_task) {
502 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
506 task_ptr_type co_task_1 = cotask::task<test_context_task_fiber_default_test_macro>::create(
507 test_context_task_fiber_await_1, 16384,
508 sizeof(cotask::task<test_context_task_fiber_default_test_macro>::self_t *));
510 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_await_2, 16384);
512 void *priv_data = co_task_1->get_private_buffer();
514 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data) = co_task_2.get();
531 task_ptr_type co_task_1 = cotask::task<test_context_task_fiber_default_test_macro>::create(
532 test_context_task_fiber_await_1, 16384,
533 sizeof(cotask::task<test_context_task_fiber_default_test_macro>::self_t *));
535 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_await_2, 16384);
537 void *priv_data = co_task_1->get_private_buffer();
542 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data) = co_task_2.get();
561 task_ptr_type co_task_1 = cotask::task<test_context_task_fiber_default_test_macro>::create(
562 test_context_task_fiber_await_1, 16384,
563 sizeof(cotask::task<test_context_task_fiber_default_test_macro>::self_t *));
565 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_await_2, 16384);
567 void *priv_data = co_task_1->get_private_buffer();
569 *
reinterpret_cast<cotask::task<test_context_task_fiber_default_test_macro>::self_t **
>(priv_data) = co_task_2.get();
585 static int test_context_task_fiber_then_action_func(
void *priv_data) {
587 ++g_test_coroutine_task_fiber_on_finished;
592 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
593 g_test_coroutine_task_fiber_status = 0;
594 g_test_coroutine_task_fiber_on_finished = 0;
597 cotask::task<test_context_task_fiber_default_test_macro>::create(test_context_task_fiber_next_action(15, 0));
598 co_task->then(test_context_task_fiber_next_action(7, 15))
599 ->then(test_context_task_fiber_next_action(99, 7))
600 ->then(test_context_task_fiber_next_action(1023, 99))
601 ->then(test_context_task_fiber_next_action(5, 1023));
611 co_task->then(test_context_task_fiber_next_action(127, 5))
612 ->then(test_context_task_fiber_then_action_func, &g_test_coroutine_task_fiber_status);
617 typedef copp::stack_pool<copp::allocator::stack_allocator_malloc> test_context_task_fiber_stack_pool_t;
618 struct test_context_task_fiber_stack_pool_test_macro_coroutine {
619 using stack_allocator_type = copp::allocator::stack_allocator_pool<test_context_task_fiber_stack_pool_t>;
620 using coroutine_type = copp::coroutine_context_fiber_container<stack_allocator_type>;
624 typedef cotask::task<test_context_task_fiber_stack_pool_test_macro_coroutine>
625 test_context_task_fiber_stack_pool_test_task_t;
627 CASE_TEST(coroutine_task_fiber, then_with_stack_pool) {
628 typedef test_context_task_fiber_stack_pool_test_task_t::ptr_t
task_ptr_type;
629 test_context_task_fiber_stack_pool_t::ptr_t
stack_pool = test_context_task_fiber_stack_pool_t::create();
631 g_test_coroutine_task_fiber_on_finished = 0;
632 g_test_coroutine_task_fiber_status = 0;
634 copp::allocator::stack_allocator_pool<test_context_task_fiber_stack_pool_t> base_alloc(
stack_pool);
636 test_context_task_fiber_stack_pool_test_task_t::create(test_context_task_fiber_next_action(15, 0), base_alloc);
637 tp->then(test_context_task_fiber_next_action(127, 15))
638 ->then(test_context_task_fiber_then_action_func, &g_test_coroutine_task_fiber_status);
644 tp->then(test_context_task_fiber_next_action(255, 127))
645 ->then(test_context_task_fiber_then_action_func, &g_test_coroutine_task_fiber_status);
652 static LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<int> g_test_context_task_fiber_test_atomic;
653 static constexpr
const int g_test_context_task_fiber_test_mt_run_times = 10000;
654 static size_t g_test_context_task_fiber_test_mt_max_run_thread_number = 0;
656 test_context_task_fiber_test_mt_thread_num = 100,
657 test_context_task_fiber_test_mt_task_num = 1000,
660 struct test_context_task_fiber_test_action_mt_thread :
public cotask::impl::task_action_impl {
664 test_context_task_fiber_test_action_mt_thread() : run_count(0) {}
666 int operator()(
void *thread_func_address) {
667 std::set<void *> thread_counter;
669 while (run_count < g_test_context_task_fiber_test_mt_run_times) {
671 ++g_test_context_task_fiber_test_atomic;
673 thread_counter.insert(thread_func_address);
678 if (g_test_context_task_fiber_test_mt_max_run_thread_number < thread_counter.size()) {
679 g_test_context_task_fiber_test_mt_max_run_thread_number = thread_counter.size();
685 struct test_context_task_fiber_test_mt_thread_runner {
686 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
688 std::vector<task_ptr_type> *task_pool;
689 test_context_task_fiber_test_mt_thread_runner(std::vector<task_ptr_type> *pool) : task_pool(pool) {}
692 bool need_continue =
true;
693 while (need_continue) {
694 need_continue =
false;
696 for (
size_t i = 0; i < task_pool->size(); ++i) {
697 if (
false == (*task_pool)[i]->is_completed()) {
698 need_continue =
true;
699 (*task_pool)[i]->resume(
this);
707 CASE_TEST(coroutine_task_fiber, mt_run_competition) {
708 typedef cotask::task<test_context_task_fiber_default_test_macro>::ptr_t
task_ptr_type;
709 std::vector<task_ptr_type> task_pool;
710 task_pool.reserve(test_context_task_fiber_test_mt_task_num);
711 for (
int i = 0; i < test_context_task_fiber_test_mt_task_num; ++i) {
712 task_pool.push_back(cotask::task<test_context_task_fiber_default_test_macro>::create(
713 test_context_task_fiber_test_action_mt_thread(), 16 * 1024));
716 g_test_context_task_fiber_test_atomic.store(0);
717 g_test_context_task_fiber_test_mt_max_run_thread_number = 0;
719 std::unique_ptr<std::thread> thds[test_context_task_fiber_test_mt_thread_num];
720 for (
int i = 0; i < test_context_task_fiber_test_mt_thread_num; ++i) {
721 thds[i].reset(
new std::thread(test_context_task_fiber_test_mt_thread_runner(&task_pool)));
724 for (
int i = 0; i < test_context_task_fiber_test_mt_thread_num; ++i) {
728 CASE_EXPECT_EQ(g_test_context_task_fiber_test_mt_run_times * test_context_task_fiber_test_mt_task_num,
729 g_test_context_task_fiber_test_atomic.load());
730 CASE_MSG_INFO() <<
"Fiber tasks are run on " << g_test_context_task_fiber_test_mt_max_run_thread_number
731 <<
" threads at most." << std::endl;
virtual int yield(void **priv_data)=0
const limit_t & get_limit() const
@ COPP_EC_IS_RUNNING
COPP_EC_IS_RUNNING.
@ COPP_EC_TASK_NOT_IN_ACTION
COPP_EC_TASK_NOT_IN_ACTION.
@ COPP_EC_ALREADY_FINISHED
COPP_EC_ALREADY_FINISHED.
@ COPP_EC_TASK_IS_EXITING
COPP_EC_TASK_IS_EXITING.
@ COPP_EC_TASK_CAN_NOT_WAIT_SELF
COPP_EC_TASK_CAN_NOT_WAIT_SELF.
@ COPP_EC_ARGS_ERROR
COPP_EC_ARGS_ERROR.
LIBCOPP_COPP_API_HEAD_ONLY Tc * get()
get current coroutine and try to convert type
LIBCOPP_COPP_API int yield(void **priv_data=nullptr) LIBCOPP_MACRO_NOEXCEPT
yield current coroutine
LIBCOPP_COTASK_API impl::task_impl * get_task() LIBCOPP_MACRO_NOEXCEPT
get current running task
std::shared_ptr< cli::cmd_option_value > value_type
my_task_t::ptr_t task_ptr_type
#define CASE_EXPECT_FALSE(c)
#define CASE_EXPECT_EQ(l, r)
#define CASE_EXPECT_GT(l, r)
#define CASE_EXPECT_NE(l, r)
#define CASE_TEST(test_name, case_name)
#define CASE_EXPECT_TRUE(c)
#define CASE_EXPECT_GE(l, r)