tb_long_t tb_semaphore_wait(tb_semaphore_ref_t semaphore, tb_long_t timeout) { // check tb_semaphore_impl_t* impl = (tb_semaphore_impl_t*)semaphore; tb_assert_and_check_return_val(semaphore && impl->semaphore && impl->semaphore != INVALID_HANDLE_VALUE, -1); // wait tb_long_t r = WaitForSingleObject(impl->semaphore, timeout >= 0? timeout : INFINITE); tb_assert_and_check_return_val(r != WAIT_FAILED, -1); // timeout? tb_check_return_val(r != WAIT_TIMEOUT, 0); // error? tb_check_return_val(r >= WAIT_OBJECT_0, -1); // check value tb_assert_and_check_return_val((tb_long_t)tb_atomic_get(&impl->value) > 0, -1); // value-- tb_atomic_fetch_and_dec(&impl->value); // ok return 1; }
tb_long_t tb_semaphore_wait(tb_semaphore_ref_t self, tb_long_t timeout) { // check tb_atomic_t* semaphore = (tb_atomic_t*)self; tb_assert_and_check_return_val(semaphore, -1); // init tb_long_t r = 0; tb_hong_t base = tb_cache_time_spak(); // wait while (1) { // get post tb_long_t post = (tb_long_t)tb_atomic_get(semaphore); // has signal? if (post > 0) { // semaphore-- tb_atomic_fetch_and_dec(semaphore); // ok r = post; break; } // no signal? else if (!post) { // timeout? if (timeout >= 0 && tb_cache_time_spak() - base >= timeout) break; else tb_msleep(200); } // error else { r = -1; break; } } return r; }
tb_void_t tb_timer_loop(tb_timer_ref_t timer) { // check tb_timer_impl_t* impl = (tb_timer_impl_t*)timer; tb_assert_and_check_return(impl); // work++ tb_atomic_fetch_and_inc(&impl->work); // init event tb_spinlock_enter(&impl->lock); if (!impl->event) impl->event = tb_event_init(); tb_spinlock_leave(&impl->lock); // loop while (!tb_atomic_get(&impl->stop)) { // the delay tb_size_t delay = tb_timer_delay(timer); if (delay) { // the event tb_spinlock_enter(&impl->lock); tb_event_ref_t event = impl->event; tb_spinlock_leave(&impl->lock); tb_check_break(event); // wait some time if (tb_event_wait(event, delay) < 0) break; } // spak ctime if (impl->ctime) tb_cache_time_spak(); // spak it if (!tb_timer_spak(timer)) break; } // work-- tb_atomic_fetch_and_dec(&impl->work); }
tb_void_t tb_aicp_loop_util(tb_aicp_ref_t aicp, tb_bool_t (*stop)(tb_cpointer_t priv), tb_cpointer_t priv) { // check tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp; tb_assert_and_check_return(impl); // the ptor tb_aicp_ptor_impl_t* ptor = impl->ptor; tb_assert_and_check_return(ptor && ptor->loop_spak); // the loop spak tb_long_t (*loop_spak)(tb_aicp_ptor_impl_t* , tb_handle_t, tb_aice_ref_t , tb_long_t ) = ptor->loop_spak; // worker++ tb_atomic_fetch_and_inc(&impl->work); // init loop tb_handle_t loop = ptor->loop_init? ptor->loop_init(ptor) : tb_null; // trace tb_trace_d("loop[%p]: init", loop); // spak ctime tb_cache_time_spak(); // loop while (1) { // spak tb_aice_t resp = {0}; tb_long_t ok = loop_spak(ptor, loop, &resp, -1); // spak ctime tb_cache_time_spak(); // failed? tb_check_break(ok >= 0); // timeout? tb_check_continue(ok); // check aico tb_aico_impl_t* aico = (tb_aico_impl_t*)resp.aico; tb_assert_and_check_continue(aico); // trace tb_trace_d("loop[%p]: spak: code: %lu, aico: %p, state: %s: %ld", loop, resp.code, aico, aico? tb_state_cstr(tb_atomic_get(&aico->state)) : "null", ok); // pending? clear state if be not accept or accept failed tb_size_t state = TB_STATE_OPENED; state = (resp.code != TB_AICE_CODE_ACPT || resp.state != TB_STATE_OK)? tb_atomic_fetch_and_pset(&aico->state, TB_STATE_PENDING, state) : tb_atomic_get(&aico->state); // killed or killing? if (state == TB_STATE_KILLED || state == TB_STATE_KILLING) { // update the aice state resp.state = TB_STATE_KILLED; // killing? update to the killed state tb_atomic_fetch_and_pset(&aico->state, TB_STATE_KILLING, TB_STATE_KILLED); } // done func, @note maybe the aico exit will be called if (resp.func && !resp.func(&resp)) { // trace #ifdef __tb_debug__ tb_trace_e("loop[%p]: done aice func failed with code: %lu at line: %lu, func: %s, file: %s!", loop, resp.code, aico->line, aico->func, aico->file); #else tb_trace_e("loop[%p]: done aice func failed with code: %lu!", loop, resp.code); #endif } // killing? update to the killed state tb_atomic_fetch_and_pset(&aico->state, TB_STATE_KILLING, TB_STATE_KILLED); // stop it? if (stop && stop(priv)) tb_aicp_kill(aicp); } // exit loop if (ptor->loop_exit) ptor->loop_exit(ptor, loop); // worker-- tb_atomic_fetch_and_dec(&impl->work); // trace tb_trace_d("loop[%p]: exit", loop); }