static tb_void_t tb_aiop_spak_wait_timeout(tb_bool_t killed, tb_cpointer_t priv) { // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)priv; tb_assert_and_check_return(aico && aico->waiting); // the impl tb_aiop_ptor_impl_t* impl = aico->impl; tb_assert_and_check_return(impl && impl->aiop); // for sock if (aico->base.type == TB_AICO_TYPE_SOCK) { // check tb_assert_and_check_return(aico->aioo); // delo aioo tb_aiop_delo(impl->aiop, aico->aioo); aico->aioo = tb_null; } // have been waited ok for the spak loop? need not spak it repeatly tb_bool_t ok = tb_false; if (!aico->wait_ok) { // the priority tb_size_t priority = tb_aice_impl_priority(&aico->aice); tb_assert_and_check_return(priority < tb_arrayn(impl->spak) && impl->spak[priority]); // trace tb_trace_d("wait: timeout: code: %lu, priority: %lu, time: %lld", aico->aice.code, priority, tb_cache_time_mclock()); // enter tb_spinlock_enter(&impl->lock); // spak aice if (!tb_queue_full(impl->spak[priority])) { // save state aico->aice.state = killed? TB_STATE_KILLED : TB_STATE_TIMEOUT; // put it tb_queue_put(impl->spak[priority], &aico->aice); // ok ok = tb_true; aico->wait_ok = 1; } else tb_assert(0); // leave tb_spinlock_leave(&impl->lock); } // work it if (ok) tb_aiop_spak_work(impl); }
static tb_void_t tb_aiop_spak_runtask_timeout(tb_bool_t killed, tb_cpointer_t priv) { // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)priv; tb_assert_and_check_return(aico && aico->waiting); // the impl tb_aiop_ptor_impl_t* impl = aico->impl; tb_assert_and_check_return(impl); // the priority tb_size_t priority = tb_aice_impl_priority(&aico->aice); tb_assert_and_check_return(priority < tb_arrayn(impl->spak) && impl->spak[priority]); // enter tb_spinlock_enter(&impl->lock); // trace tb_trace_d("runtask: timeout: code: %lu, priority: %lu, size: %lu", aico->aice.code, priority, tb_queue_size(impl->spak[priority])); // spak aice tb_bool_t ok = tb_false; if (!tb_queue_full(impl->spak[priority])) { // save state aico->aice.state = killed? TB_STATE_KILLED : TB_STATE_OK; // put it tb_queue_put(impl->spak[priority], &aico->aice); // ok ok = tb_true; } else tb_assert(0); // leave tb_spinlock_leave(&impl->lock); // work it if (ok) tb_aiop_spak_work(impl); }
static tb_bool_t tb_aiop_push_sock(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(impl && aice && aice->aico, tb_false); // the priority tb_size_t priority = tb_aice_impl_priority(aice); tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); // this aico is killed? post to higher priority queue if (tb_aico_impl_is_killed((tb_aico_impl_t*)aice->aico)) priority = 0; // trace tb_trace_d("push: aico: %p, handle: %p, code: %lu, priority: %lu", aice->aico, tb_aico_sock(aice->aico), aice->code, priority); // enter tb_spinlock_enter(&impl->lock); // not full? if (!tb_queue_full(impl->spak[priority])) { // push aice to the spak queue tb_queue_put(impl->spak[priority], aice); // wait ok if be not acpt aice if (aice->code != TB_AICE_CODE_ACPT) ((tb_aiop_aico_t*)aice->aico)->wait_ok = 1; } else { // trace tb_trace_e("push: failed, the spak queue is full!"); } // leave tb_spinlock_leave(&impl->lock); // ok return tb_true; }
static tb_bool_t tb_aiop_push_acpt(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(impl && aice, tb_false); tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_ACPT, tb_false); // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; tb_assert_and_check_return_val(aico && aico->base.handle, tb_false); // the priority tb_size_t priority = tb_aice_impl_priority(aice); tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); // init the acpt aice tb_aice_t acpt_aice = *aice; acpt_aice.state = TB_STATE_OK; // done tb_size_t list_indx = 0; tb_size_t list_size = 0; tb_socket_ref_t list_sock[2048]; tb_ipaddr_t list_addr[2048]; tb_size_t list_maxn = tb_arrayn(list_sock); tb_socket_ref_t acpt = (tb_socket_ref_t)aico->base.handle; tb_queue_ref_t spak = impl->spak[priority]; tb_socket_ref_t sock = tb_null; do { // accept it for (list_size = 0; list_size < list_maxn && (list_sock[list_size] = tb_socket_accept(acpt, list_addr + list_size)); list_size++) ; // enter tb_spinlock_enter(&impl->lock); // push some acpt aice for (list_indx = 0; list_indx < list_size && (sock = list_sock[list_indx]); list_indx++) { // init aico acpt_aice.u.acpt.aico = tb_aico_init(aico->base.aicp); // trace tb_trace_d("push: acpt[%p]: sock: %p, aico: %p", aico->base.handle, sock, acpt_aice.u.acpt.aico); // open aico and push the acpt aice if not full? if ( acpt_aice.u.acpt.aico && tb_aico_open_sock(acpt_aice.u.acpt.aico, sock) && !tb_queue_full(spak)) { // save addr tb_ipaddr_copy(&acpt_aice.u.acpt.addr, list_addr + list_indx); // push to the spak queue tb_queue_put(spak, &acpt_aice); } else { // close the left sock tb_size_t i; for (i = list_indx; i < list_size; i++) { // close it if (list_sock[i]) tb_socket_exit(list_sock[i]); list_sock[i] = tb_null; } // exit aico if (acpt_aice.u.acpt.aico) tb_aico_exit(acpt_aice.u.acpt.aico); acpt_aice.u.acpt.aico = tb_null; // trace tb_trace_e("push: acpt failed!"); break; } } // leave tb_spinlock_leave(&impl->lock); } while (list_indx == list_maxn); // ok return tb_true; }
static tb_bool_t tb_aiop_ptor_post(tb_aicp_ptor_impl_t* ptor, tb_aice_t const* aice) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; tb_assert_and_check_return_val(impl && aice && aice->aico, tb_false); // optimizate to spak the clos aice if (aice->code == TB_AICE_CODE_CLOS) { // spak the clos tb_aice_t resp = *aice; if (tb_aiop_spak_clos(impl, &resp) <= 0) return tb_false; // done the aice response function aice->func(&resp); // post ok return tb_true; } // the priority tb_size_t priority = tb_aice_impl_priority(aice); tb_assert_and_check_return_val(priority < tb_arrayn(impl->spak) && impl->spak[priority], tb_false); // done tb_bool_t ok = tb_true; tb_aico_impl_t* aico = (tb_aico_impl_t*)aice->aico; switch (aico->type) { case TB_AICO_TYPE_SOCK: case TB_AICO_TYPE_TASK: { // enter tb_spinlock_enter(&impl->lock); // post aice if (!tb_queue_full(impl->spak[priority])) { // put tb_queue_put(impl->spak[priority], aice); // trace tb_trace_d("post: code: %lu, priority: %lu, size: %lu", aice->code, priority, tb_queue_size(impl->spak[priority])); } else { // failed ok = tb_false; // trace tb_trace_e("post: code: %lu, priority: %lu, size: %lu: failed", aice->code, priority, tb_queue_size(impl->spak[priority])); } // leave tb_spinlock_leave(&impl->lock); } break; case TB_AICO_TYPE_FILE: { // post file ok = tb_aicp_file_post(impl, aice); } break; default: ok = tb_false; break; } // work it if (ok) tb_aiop_spak_work(impl); // ok? return ok; }