Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}
Exemple #4
0
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);
}