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_ptor_kill(tb_aicp_ptor_impl_t* ptor) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)ptor; tb_assert_and_check_return(impl && impl->timer && impl->ltimer && impl->aiop); // trace tb_trace_d("kill: .."); // kill aiop tb_aiop_kill(impl->aiop); // kill file tb_aicp_file_kill(impl); // work it 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_pointer_t tb_aiop_spak_loop(tb_cpointer_t priv) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)priv; tb_aicp_impl_t* aicp = impl? impl->base.aicp : tb_null; // done do { // check tb_assert_and_check_break(impl && impl->aiop && impl->list && impl->timer && impl->ltimer && aicp); // trace tb_trace_d("loop: init"); // loop while (!tb_atomic_get(&aicp->kill)) { // the delay tb_size_t delay = tb_timer_delay(impl->timer); // the ldelay tb_size_t ldelay = tb_ltimer_delay(impl->ltimer); tb_assert_and_check_break(ldelay != -1); // trace tb_trace_d("loop: wait: .."); // wait aioe tb_long_t real = tb_aiop_wait(impl->aiop, impl->list, impl->maxn, tb_min(delay, ldelay)); // trace tb_trace_d("loop: wait: %ld", real); // spak ctime tb_cache_time_spak(); // spak timer if (!tb_timer_spak(impl->timer)) break; // spak ltimer if (!tb_ltimer_spak(impl->ltimer)) break; // killed? tb_check_break(real >= 0); // error? out of range tb_assert_and_check_break(real <= impl->maxn); // timeout? tb_check_continue(real); // grow it if aioe is full if (real == impl->maxn) { // grow size impl->maxn += (aicp->maxn >> 4) + 16; if (impl->maxn > aicp->maxn) impl->maxn = aicp->maxn; // grow list impl->list = tb_ralloc(impl->list, impl->maxn * sizeof(tb_aioe_t)); tb_assert_and_check_break(impl->list); } // walk aioe list tb_size_t i = 0; tb_bool_t end = tb_false; for (i = 0; i < real && !end; i++) { // the aioe tb_aioe_ref_t aioe = &impl->list[i]; tb_assert_and_check_break_state(aioe, end, tb_true); // the aice tb_aice_ref_t aice = (tb_aice_ref_t)aioe->priv; tb_assert_and_check_break_state(aice, end, tb_true); // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; tb_assert_and_check_break_state(aico, end, tb_true); // have wait? tb_check_continue(aice->code); // have been waited ok for the timer timeout/killed func? need not spak it repeatly tb_check_continue(!aico->wait_ok); // sock? if (aico->base.type == TB_AICO_TYPE_SOCK) { // push the acpt aice if (aice->code == TB_AICE_CODE_ACPT) end = tb_aiop_push_acpt(impl, aice)? tb_false : tb_true; // push the sock aice else end = tb_aiop_push_sock(impl, aice)? tb_false : tb_true; } else if (aico->base.type == TB_AICO_TYPE_FILE) { // poll file tb_aicp_file_poll(impl); } else tb_assert(0); } // end? tb_check_break(!end); // work it tb_aiop_spak_work(impl); } } while (0); // trace tb_trace_d("loop: exit"); // kill tb_aicp_kill((tb_aicp_ref_t)aicp); // exit tb_thread_return(tb_null); return tb_null; }
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; }