tb_aioo_ref_t tb_aiop_addo(tb_aiop_ref_t aiop, tb_socket_ref_t sock, tb_size_t code, tb_cpointer_t priv) { // check tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; tb_assert_and_check_return_val(impl && impl->rtor && impl->rtor->addo && sock, tb_null); tb_assert(tb_aiop_have(aiop, code)); // done tb_bool_t ok = tb_false; tb_aioo_ref_t aioo = tb_null; do { // init aioo aioo = tb_aiop_aioo_init(impl, sock, code, priv); tb_assert_and_check_break(aioo); // addo aioo if (!impl->rtor->addo(impl->rtor, (tb_aioo_impl_t*)aioo)) break; // ok ok = tb_true; } while (0); // failed? remove aioo if (!ok && aioo) { tb_aiop_aioo_exit(impl, aioo); aioo = tb_null; } // ok? return aioo; }
tb_bool_t tb_aiop_post(tb_aiop_ref_t aiop, tb_aioe_ref_t aioe) { // check tb_aiop_impl_t* impl = (tb_aiop_impl_t*)aiop; tb_assert_and_check_return_val(impl && impl->rtor && impl->rtor->post && aioe, tb_false); tb_assert(tb_aiop_have(aiop, aioe->code)); // post return impl->rtor->post(impl->rtor, aioe); }
static tb_bool_t tb_aiop_spak_wait(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice) { // check tb_assert_and_check_return_val(impl && impl->aiop && impl->ltimer && aice, 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 && !aico->task, tb_false); // the aioe code tb_size_t code = tb_aiop_aioe_code(aice); tb_assert_and_check_return_val(code != TB_AIOE_CODE_NONE, tb_false); // trace tb_trace_d("wait: aico: %p, code: %lu: time: %lld: ..", aico, aice->code, tb_cache_time_mclock()); // done tb_bool_t ok = tb_false; tb_aice_t prev = aico->aice; do { // wait it aico->aice = *aice; aico->waiting = 1; aico->wait_ok = 0; // wait once if not accept if (aice->code != TB_AICE_CODE_ACPT) code |= TB_AIOE_CODE_ONESHOT; // using the edge triggered mode if (tb_aiop_have(impl->aiop, TB_AIOE_CODE_CLEAR)) code |= TB_AIOE_CODE_CLEAR; // have aioo? if (!aico->aioo) { // addo wait if (!(aico->aioo = tb_aiop_addo(impl->aiop, aico->base.handle, code, &aico->aice))) break; } else { // sete wait if (!tb_aiop_sete(impl->aiop, aico->aioo, code, &aico->aice)) break; } // add timeout task tb_long_t timeout = tb_aico_impl_timeout_from_code((tb_aico_impl_t*)aico, aice->code); if (timeout >= 0) { // add it aico->task = tb_ltimer_task_init(impl->ltimer, timeout, tb_false, tb_aiop_spak_wait_timeout, aico); tb_assert_and_check_break(aico->task); aico->bltimer = 1; } // ok ok = tb_true; } while (0); // failed? restore it if (!ok) { // trace tb_trace_d("wait: aico: %p, code: %lu: failed", aico, aice->code); // restore it aico->aice = prev; aico->waiting = 0; } // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }