tb_void_t tb_poller_clear(tb_poller_ref_t self) { // check tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self; tb_assert_and_check_return(poller); // clear hash if (poller->hash) tb_memset(poller->hash, 0, poller->hash_size * sizeof(tb_cpointer_t)); // clear pfds if (poller->pfds) tb_vector_clear(poller->pfds); // clear cfds if (poller->cfds) tb_vector_clear(poller->cfds); // spak it if (poller->pair[0]) tb_socket_send(poller->pair[0], (tb_byte_t const*)"p", 1); }
static tb_void_t tb_aiop_rtor_poll_cler(tb_aiop_rtor_impl_t* rtor) { tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor; if (impl) { // clear pfds tb_spinlock_enter(&impl->lock.pfds); if (impl->pfds) tb_vector_clear(impl->pfds); tb_spinlock_leave(&impl->lock.pfds); // clear hash tb_spinlock_enter(&impl->lock.hash); if (impl->hash) tb_hash_clear(impl->hash); tb_spinlock_leave(&impl->lock.hash); // spak it if (rtor->aiop && rtor->aiop->spak[0]) tb_socket_send(rtor->aiop->spak[0], (tb_byte_t const*)"p", 1); } }
static tb_bool_t tb_aiop_rtor_poll_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo) { // check tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor; tb_assert_and_check_return_val(impl && impl->pfds && impl->cfds && aioo && aioo->sock, tb_false); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, tb_false); // add sock => aioo tb_bool_t ok = tb_false; tb_spinlock_enter(&impl->lock.hash); if (impl->hash) { tb_hash_set(impl->hash, aioo->sock, aioo); ok = tb_true; } tb_spinlock_leave(&impl->lock.hash); tb_assert_and_check_return_val(ok, tb_false); // the code tb_size_t code = aioo->code; // init pfd struct pollfd pfd = {0}; pfd.fd = ((tb_long_t)aioo->sock) - 1; if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) pfd.events |= POLLIN; if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) pfd.events |= POLLOUT; // add pfd, TODO: addo by binary search tb_spinlock_enter(&impl->lock.pfds); tb_vector_insert_tail(impl->pfds, &pfd); tb_spinlock_leave(&impl->lock.pfds); // spak it if (aiop->spak[0] && code) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1); // ok? return ok; }
tb_void_t tb_aiop_spak(tb_aiop_ref_t aiop) { // check tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; tb_assert_and_check_return(impl); // spak it if (impl->spak[0]) { // post: 'p' tb_long_t ok = tb_socket_send(impl->spak[0], (tb_byte_t const*)"p", 1); if (ok != 1) { // trace tb_trace_e("spak: failed!"); // abort it tb_assert(0); } } }
static tb_bool_t tb_aiop_rtor_select_post(tb_aiop_rtor_impl_t* rtor, tb_aioe_t const* aioe) { // check tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor; tb_assert_and_check_return_val(impl && aioe, tb_false); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, tb_false); // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)aioe->aioo; tb_assert_and_check_return_val(aioo && aioo->sock, tb_false); // save aioo aioo->code = aioe->code; aioo->priv = aioe->priv; // fd tb_long_t fd = tb_sock2fd(aioo->sock); // enter tb_spinlock_enter(&impl->lock.pfds); // set fds if (aioe->code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_ACPT)) FD_SET(fd, &impl->rfdi); else FD_CLR(fd, &impl->rfdi); if (aioe->code & (TB_AIOE_CODE_SEND | TB_AIOE_CODE_CONN)) FD_SET(fd, &impl->wfdi); else FD_CLR(fd, &impl->wfdi); // leave tb_spinlock_leave(&impl->lock.pfds); // spak it if (aiop->spak[0]) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1); // ok return tb_true; }
static tb_void_t tb_aiop_rtor_select_cler(tb_aiop_rtor_impl_t* rtor) { tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor; if (impl) { // free fds tb_spinlock_enter(&impl->lock.pfds); impl->sfdm = 0; FD_ZERO(&impl->rfdi); FD_ZERO(&impl->wfdi); FD_ZERO(&impl->rfdo); FD_ZERO(&impl->wfdo); tb_spinlock_leave(&impl->lock.pfds); // clear hash tb_spinlock_enter(&impl->lock.hash); if (impl->hash) tb_hash_map_clear(impl->hash); tb_spinlock_leave(&impl->lock.hash); // spak it if (rtor->aiop && rtor->aiop->spak[0]) tb_socket_send(rtor->aiop->spak[0], (tb_byte_t const*)"p", 1); } }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_asio_aiopd_main(tb_int_t argc, tb_char_t** argv) { // check tb_assert_and_check_return_val(argv[1], 0); // done tb_socket_ref_t sock = tb_null; tb_aiop_ref_t aiop = tb_null; do { // init sock sock = tb_socket_init(TB_SOCKET_TYPE_TCP); tb_assert_and_check_break(sock); // init aiop aiop = tb_aiop_init(16); tb_assert_and_check_break(aiop); // bind if (!tb_socket_bind(sock, tb_null, 9090)) break; // listen sock if (!tb_socket_listen(sock, 20)) break; // addo sock if (!tb_aiop_addo(aiop, sock, TB_AIOE_CODE_ACPT, tb_null)) break; // accept tb_aioe_t list[16]; while (1) { // wait tb_long_t objn = tb_aiop_wait(aiop, list, 16, -1); tb_assert_and_check_break(objn >= 0); // walk list tb_size_t i = 0; for (i = 0; i < objn; i++) { // the aioo tb_aioo_ref_t aioo = list[i].aioo; // check tb_assert_and_check_break(aioo && tb_aioo_sock(aioo)); // acpt? if (list[i].code & TB_AIOE_CODE_ACPT) { // done acpt tb_bool_t ok = tb_false; tb_demo_context_t* context = tb_null; do { // make context context = tb_malloc0_type(tb_demo_context_t); tb_assert_and_check_break(context); // init sock context->sock = tb_socket_accept(tb_aioo_sock(aioo), tb_null, tb_null); tb_assert_and_check_break(context->sock); // init file context->file = tb_file_init(argv[1], TB_FILE_MODE_RO); tb_assert_and_check_break(context->file); // init data context->data = tb_malloc_bytes(TB_DEMO_FILE_READ_MAXN); tb_assert_and_check_break(context->data); // addo sock context->aioo = tb_aiop_addo(aiop, context->sock, TB_AIOE_CODE_SEND, context); tb_assert_and_check_break(context->aioo); // trace tb_trace_i("acpt[%p]: ok", context->sock); // init left context->left = tb_file_size(context->file); // done read tb_long_t real = tb_file_read(context->file, context->data, tb_min((tb_size_t)context->left, TB_DEMO_FILE_READ_MAXN)); tb_assert_and_check_break(real > 0); // save size context->left -= real; // trace // tb_trace_i("read[%p]: real: %ld", context->file, real); // done send context->send = real; real = tb_socket_send(context->sock, context->data + context->real, context->send - context->real); if (real >= 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", context->sock, real); } else { // trace tb_trace_i("send[%p]: closed", context->sock); break; } // ok ok = tb_true; } while (0); // failed or closed? if (!ok) { // exit context tb_demo_context_exit(aiop, context); break; } } // writ? else if (list[i].code & TB_AIOE_CODE_SEND) { // the context tb_demo_context_t* context = (tb_demo_context_t*)list[i].priv; tb_assert_and_check_break(context); // continue to send it if not finished if (context->real < context->send) { // done send tb_long_t real = tb_socket_send(tb_aioo_sock(aioo), context->data + context->real, context->send - context->real); if (real > 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", tb_aioo_sock(aioo), real); } else { // trace tb_trace_i("send[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } // finished? read file else if (context->left) { // init context->real = 0; context->send = 0; // done read tb_size_t tryn = 1; tb_long_t real = 0; while (!(real = tb_file_read(context->file, context->data, tb_min((tb_size_t)context->left, TB_DEMO_FILE_READ_MAXN))) && tryn--); if (real > 0) { // save left context->left -= real; // trace // tb_trace_i("read[%p]: real: %ld", context->file, real); // done send context->send = real; real = tb_socket_send(tb_aioo_sock(aioo), context->data, context->send); if (real >= 0) { // save real context->real += real; // trace // tb_trace_i("send[%p]: real: %ld", tb_aioo_sock(aioo), real); } else { // trace tb_trace_i("send[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } else { // trace tb_trace_i("read[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } else { // trace tb_trace_i("read[%p]: closed", tb_aioo_sock(aioo)); // exit context tb_demo_context_exit(aiop, context); break; } } // error? else { tb_trace_i("aioe[%p]: unknown code: %lu", tb_aioo_sock(aioo), list[i].code); break; } } } } while (0); // trace tb_trace_i("end"); // exit socket if (sock) tb_socket_exit(sock); // exit aiop if (aiop) tb_aiop_exit(aiop); // end return 0; }