/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_platform_thread_local_main(tb_int_t argc, tb_char_t** argv) { tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0); tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0); tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0); tb_thread_init(tb_null, tb_demo_thread_local_test, tb_null, 0); tb_thread_init(tb_null, tb_demo_thread_local_stub, tb_null, 0); // wait getchar(); return 0; }
static tb_handle_t tb_aicp_instance_init(tb_cpointer_t* ppriv) { // check tb_assert_and_check_return_val(ppriv, tb_null); // done tb_bool_t ok = tb_false; tb_aicp_ref_t aicp = tb_null; do { // init aicp aicp = tb_aicp_init(0); tb_assert_and_check_break(aicp); // init loop *ppriv = (tb_cpointer_t)tb_thread_init(tb_null, tb_aicp_instance_loop, aicp, 0); tb_assert_and_check_break(*ppriv); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit aicp if (aicp) tb_aicp_exit(aicp); aicp = tb_null; } // ok? return (tb_handle_t)aicp; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_coroutine_http_server_main(tb_int_t argc, tb_char_t** argv) { // done tb_socket_ref_t sock = tb_null; do { // init socket sock = tb_socket_init(TB_SOCKET_TYPE_TCP, TB_IPADDR_FAMILY_IPV4); tb_assert_and_check_break(sock); // bind socket tb_ipaddr_t addr; tb_ipaddr_set(&addr, tb_null, TB_DEMO_PORT, TB_IPADDR_FAMILY_IPV4); if (!tb_socket_bind(sock, &addr)) break; // listen socket if (!tb_socket_listen(sock, 1000)) break; // init the root directory if (argv[1]) tb_strlcpy(g_rootdir, argv[1], sizeof(g_rootdir)); else tb_directory_current(g_rootdir, sizeof(g_rootdir)); // only data? if (!tb_file_info(g_rootdir, tb_null)) g_onlydata = tb_true; // trace tb_trace_i("%s: %s", g_onlydata? "data" : "rootdir", g_rootdir); #if TB_DEMO_CPU > 1 // start workers for multi-threads tb_size_t count = TB_DEMO_CPU - 1; while (count--) tb_thread_init(tb_null, tb_demo_coroutine_worker, sock, 0); #endif // start worker tb_demo_coroutine_worker(sock); } while (0); // exit socket if (sock) tb_socket_exit(sock); sock = tb_null; // ok return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_platform_semaphore_main(tb_int_t argc, tb_char_t** argv) { // init loop tb_demo_loop_t loop[10]; tb_size_t i = 0; tb_size_t n = tb_arrayn(loop); for (i = 0; i < n; i++) { // init semaphore loop[i].semaphore = tb_semaphore_init(0); tb_assert_and_check_break(loop[i].semaphore); // post semaphore tb_semaphore_post(loop[i].semaphore, 1); // init index loop[i].index = i; // init stoped loop[i].bstoped = 0; // init loop loop[i].loop = tb_thread_init(tb_null, tb_demo_loop, loop + i, 0); tb_assert_and_check_break(loop[i].loop); } // check tb_assert_and_check_return_val(i == n, 0); // wait some time tb_msleep(100); // post tb_char_t line[256]; tb_bool_t stop = tb_false; while (!stop) { // get line tb_char_t const* p = tb_demo_gets(line, sizeof(line)); tb_assert_and_check_break(p); // trace tb_trace_i("post: %s", p); // done while (*p && !stop) { tb_char_t ch = *p++; switch (ch) { case 'q': stop = tb_true; break; default: { if (ch >= '0' && ch <= '9') { // the index tb_size_t index = ch - '0'; tb_assert_and_check_break(index < n && index == loop[index].index); // post semaphore if (loop[index].semaphore) tb_semaphore_post(loop[index].semaphore, 1); } } break; } } } // post loop for (i = 0; i < n; i++) { // quit thread tb_atomic_set(&loop[i].bstoped, 1); // post semaphore if (loop[i].semaphore) tb_semaphore_post(loop[i].semaphore, 1); } // exit loop for (i = 0; i < n; i++) { // exit loop if (loop[i].loop) { // wait it if (!tb_thread_wait(loop[i].loop, 5000)) { // trace tb_trace_e("wait loop[%lu]: timeout", i); } // exit it tb_thread_exit(loop[i].loop); } // exit semaphore if (loop[i].semaphore) tb_semaphore_exit(loop[i].semaphore); } // exit tb_trace_i("exit"); return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_asio_aicpd_main(tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(argv[1], 0); // init tb_aicp_ref_t aicp = tb_null; tb_aico_ref_t aico = tb_null; // tb_aico_ref_t task = tb_null; tb_thread_ref_t loop[16] = {tb_null}; do { // init aicp aicp = tb_aicp_init(16); tb_assert_and_check_break(aicp); // init sock aico aico = tb_aico_init(aicp); tb_assert_and_check_break(aico); // init addr tb_ipaddr_t addr; tb_ipaddr_set(&addr, tb_null, 9090, TB_IPADDR_FAMILY_IPV4); // open sock aico if (!tb_aico_open_sock_from_type(aico, TB_SOCKET_TYPE_TCP, tb_ipaddr_family(&addr))) break; // bind port if (!tb_socket_bind(tb_aico_sock(aico), &addr)) break; // listen sock if (!tb_socket_listen(tb_aico_sock(aico), 20)) break; #if 0 // init task aico task = tb_aico_init(aicp); tb_assert_and_check_break(task); // open task aico if (!tb_aico_open_task(task, tb_false)) break; // run task if (!tb_aico_task_run(task, 0, tb_demo_task_func, tb_null)) break; if (!tb_aico_task_run(aico, 0, tb_demo_task_func, tb_null)) break; #endif // post acpt if (!tb_aico_acpt(aico, tb_demo_sock_acpt_func, argv[1])) break; // done loop loop[0] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); loop[1] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); loop[2] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); loop[3] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0); // wait exit getchar(); } while (0); // trace tb_trace_i("end"); #if 1 if (aicp) { // kill all tb_aicp_kill_all(aicp); // wait all tb_aicp_wait_all(aicp, -1); // kill aicp tb_aicp_kill(aicp); } // wait exit { // exit loop tb_thread_ref_t* l = loop; for (; *l; l++) { tb_thread_wait(*l, -1, tb_null); tb_thread_exit(*l); } } #endif // exit aicp if (aicp) tb_aicp_exit(aicp); return 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ static tb_aicp_ptor_impl_t* tb_aiop_ptor_init(tb_aicp_impl_t* aicp) { // check tb_assert_and_check_return_val(aicp && aicp->maxn, tb_null); // done tb_bool_t ok = tb_false; tb_aiop_ptor_impl_t* impl = tb_null; do { // make ptor impl = tb_malloc0_type(tb_aiop_ptor_impl_t); tb_assert_and_check_break(impl); // init base impl->base.aicp = aicp; impl->base.step = sizeof(tb_aiop_aico_t); impl->base.kill = tb_aiop_ptor_kill; impl->base.exit = tb_aiop_ptor_exit; impl->base.addo = tb_aiop_ptor_addo; impl->base.kilo = tb_aiop_ptor_kilo; impl->base.post = tb_aiop_ptor_post; impl->base.loop_spak = tb_aiop_ptor_spak; // init lock if (!tb_spinlock_init(&impl->lock)) break; // init wait impl->wait = tb_semaphore_init(0); tb_assert_and_check_break(impl->wait); // init aiop impl->aiop = tb_aiop_init(aicp->maxn); tb_assert_and_check_break(impl->aiop); // check tb_assert_and_check_break(tb_aiop_have(impl->aiop, TB_AIOE_CODE_EALL | TB_AIOE_CODE_ONESHOT)); // init spak impl->spak[0] = tb_queue_init((aicp->maxn >> 4) + 16, tb_item_func_mem(sizeof(tb_aice_t), tb_null, tb_null)); impl->spak[1] = tb_queue_init((aicp->maxn >> 4) + 16, tb_item_func_mem(sizeof(tb_aice_t), tb_null, tb_null)); tb_assert_and_check_break(impl->spak[0] && impl->spak[1]); // init file if (!tb_aicp_file_init(impl)) break; // init list impl->maxn = (aicp->maxn >> 4) + 16; impl->list = tb_nalloc0(impl->maxn, sizeof(tb_aioe_t)); tb_assert_and_check_break(impl->list); // init timer and using cache time impl->timer = tb_timer_init((aicp->maxn >> 4) + 16, tb_true); tb_assert_and_check_break(impl->timer); // init ltimer and using cache time impl->ltimer = tb_ltimer_init(aicp->maxn, TB_LTIMER_TICK_S, tb_true); tb_assert_and_check_break(impl->ltimer); // register lock profiler #ifdef TB_LOCK_PROFILER_ENABLE tb_lock_profiler_register(tb_lock_profiler(), (tb_pointer_t)&impl->lock, "aicp_aiop"); #endif // init loop impl->loop = tb_thread_init(tb_null, tb_aiop_spak_loop, impl, 0); tb_assert_and_check_break(impl->loop); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (impl) tb_aiop_ptor_exit((tb_aicp_ptor_impl_t*)impl); return tb_null; } // ok? return (tb_aicp_ptor_impl_t*)impl; }
static tb_thread_pool_job_t* tb_thread_pool_jobs_post_task(tb_thread_pool_impl_t* impl, tb_thread_pool_task_t const* task, tb_size_t* post_size) { // check tb_assert_and_check_return_val(impl && task && task->done && post_size, tb_null); // done tb_bool_t ok = tb_false; tb_thread_pool_job_t* job = tb_null; do { // check tb_assert_and_check_break(tb_list_entry_size(&impl->jobs_waiting) + tb_list_entry_size(&impl->jobs_urgent) + 1 < TB_THREAD_POOL_JOBS_WAITING_MAXN); // make job job = (tb_thread_pool_job_t*)tb_fixed_pool_malloc0(impl->jobs_pool); tb_assert_and_check_break(job); // init job job->refn = 1; job->state = TB_STATE_WAITING; job->task = *task; // non-urgent job? if (!task->urgent) { // post to the waiting jobs tb_list_entry_insert_tail(&impl->jobs_waiting, &job->entry); } else { // post to the urgent jobs tb_list_entry_insert_tail(&impl->jobs_urgent, &job->entry); } // the waiting jobs count tb_size_t jobs_waiting_count = tb_list_entry_size(&impl->jobs_waiting) + tb_list_entry_size(&impl->jobs_urgent); tb_assert_and_check_break(jobs_waiting_count); // update the post size if (*post_size < impl->worker_size) (*post_size)++; // trace tb_trace_d("task[%p:%s]: post: %lu: ..", task->done, task->name, *post_size); // init them if the workers have been not inited if (impl->worker_size < jobs_waiting_count) { tb_size_t i = impl->worker_size; tb_size_t n = tb_min(jobs_waiting_count, impl->worker_maxn); for (; i < n; i++) { // the worker tb_thread_pool_worker_t* worker = &impl->worker_list[i]; // clear worker tb_memset(worker, 0, sizeof(tb_thread_pool_worker_t)); // init worker worker->id = i; worker->pool = (tb_thread_pool_ref_t)impl; worker->loop = tb_thread_init(__tb_lstring__("thread_pool"), tb_thread_pool_worker_loop, worker, impl->stack); tb_assert_and_check_continue(worker->loop); } // update the worker size impl->worker_size = i; } // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it tb_fixed_pool_free(impl->jobs_pool, job); job = tb_null; } // ok? return job; }