Пример #1
0
static tb_void_t tb_aicp_instance_exit(tb_handle_t handle, tb_cpointer_t priv)
{
    // check
    tb_assert_and_check_return(handle);

    // wait all
    if (!tb_aicp_wait_all((tb_aicp_ref_t)handle, 5000)) return ;

    // kill aicp
    tb_aicp_kill((tb_aicp_ref_t)handle);

    // exit loop
    tb_thread_ref_t loop = (tb_thread_ref_t)priv;
    if (loop)
    {
        // wait it
        if (!tb_thread_wait(loop, 5000)) return ;

        // exit it
        tb_thread_exit(loop);
    }

    // exit it
    tb_aicp_exit((tb_aicp_ref_t)handle);
}
Пример #2
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_void_t tb_demo_sock_dns_done_func(tb_aicp_dns_ref_t dns, tb_char_t const* host, tb_ipv4_t const* addr, tb_cpointer_t priv)
{
    // check
    tb_assert_and_check_return(dns);

    // the aicp
    tb_aicp_ref_t aicp = tb_aicp_dns_aicp(dns);
    tb_assert_and_check_return(aicp);

    // addr ok?
    if (addr)
    {
        // trace
        tb_trace_i("dns[%s]: %u.%u.%u.%u", host, addr->u8[0], addr->u8[1], addr->u8[2], addr->u8[3]);
    }
    // timeout or failed?
    else
    {
        // trace
        tb_trace_i("dns[%s]: failed", host);
    }

    // exit addr
    if (dns) tb_aicp_dns_exit(dns);

    // kill aicp
    tb_aicp_kill(aicp);
}
Пример #3
0
tb_bool_t tb_aicp_exit(tb_aicp_ref_t aicp)
{
    // check
    tb_aicp_impl_t* impl = (tb_aicp_impl_t*)aicp;
    tb_assert_and_check_return_val(impl, tb_false);

    // kill all first
    tb_aicp_kill_all((tb_aicp_ref_t)impl);

    // wait all exiting
    if (tb_aicp_wait_all((tb_aicp_ref_t)impl, 5000) <= 0) 
    {
        // wait failed, trace left aicos
        tb_spinlock_enter(&impl->lock);
        if (impl->pool) tb_fixed_pool_walk(impl->pool, tb_aicp_walk_wait, tb_null);
        tb_spinlock_leave(&impl->lock);
        return tb_false;
    }
   
    // kill loop
    tb_aicp_kill((tb_aicp_ref_t)impl);

    // wait workers exiting 
    tb_hong_t time = tb_mclock();
    while (tb_atomic_get(&impl->work) && (tb_mclock() < time + 5000)) tb_msleep(500);

    // exit proactor
    if (impl->ptor)
    {
        tb_assert(impl->ptor && impl->ptor->exit);
        impl->ptor->exit(impl->ptor);
        impl->ptor = tb_null;
    }

    // exit aico pool
    tb_spinlock_enter(&impl->lock);
    if (impl->pool) tb_fixed_pool_exit(impl->pool);
    impl->pool = tb_null;
    tb_spinlock_leave(&impl->lock);

    // exit lock
    tb_spinlock_exit(&impl->lock);

    // free impl
    tb_free(impl);

    // ok
    return tb_true;
}
Пример #4
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_bool_t tb_demo_sock_aico_clos(tb_aice_t const* aice)
{
    // check
    tb_assert_and_check_return_val(aice && aice->aico && aice->code == TB_AICE_CODE_CLOS, tb_false);

    // trace
    tb_trace_d("aico[%p]: clos: %s", aice->aico, tb_state_cstr(aice->state));

    // exit aico
    tb_aico_exit(aice->aico);

    // kill aicp
    tb_aicp_kill(tb_aico_aicp(aice->aico));

    // ok
    return tb_true;
}
Пример #5
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);
}
Пример #6
0
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;
}
Пример #7
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * main
 */
tb_int_t tb_demo_asio_aicpd_main(tb_int_t argc, tb_char_t** argv)
{
    // check
    tb_assert_and_check_return_val(argv[1], 0);

    // init
    tb_aicp_ref_t       aicp = tb_null;
    tb_aico_ref_t       aico = tb_null;
//    tb_aico_ref_t       task = tb_null;
    tb_thread_ref_t     loop[16] = {tb_null};
    do
    {
        // init aicp
        aicp = tb_aicp_init(16);
        tb_assert_and_check_break(aicp);

        // init sock aico
        aico = tb_aico_init(aicp);
        tb_assert_and_check_break(aico);

        // init addr
        tb_ipaddr_t addr;
        tb_ipaddr_set(&addr, tb_null, 9090, TB_IPADDR_FAMILY_IPV4);

        // open sock aico
        if (!tb_aico_open_sock_from_type(aico, TB_SOCKET_TYPE_TCP, tb_ipaddr_family(&addr))) break;

        // bind port
        if (!tb_socket_bind(tb_aico_sock(aico), &addr)) break;

        // listen sock
        if (!tb_socket_listen(tb_aico_sock(aico), 20)) break;

#if 0
        // init task aico
        task = tb_aico_init(aicp);
        tb_assert_and_check_break(task);

        // open task aico
        if (!tb_aico_open_task(task, tb_false)) break;

        // run task
        if (!tb_aico_task_run(task, 0, tb_demo_task_func, tb_null)) break;
        if (!tb_aico_task_run(aico, 0, tb_demo_task_func, tb_null)) break;
#endif

        // post acpt
        if (!tb_aico_acpt(aico, tb_demo_sock_acpt_func, argv[1])) break;

        // done loop
        loop[0] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0);
        loop[1] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0);
        loop[2] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0);
        loop[3] = tb_thread_init(tb_null, tb_demo_loop, aicp, 0);

        // wait exit
        getchar();

    } while (0);

    // trace
    tb_trace_i("end");
 
#if 1
    if (aicp)
    {
        // kill all
        tb_aicp_kill_all(aicp);
   
        // wait all
        tb_aicp_wait_all(aicp, -1);

        // kill aicp
        tb_aicp_kill(aicp);
    }

    // wait exit
    {
        // exit loop
        tb_thread_ref_t* l = loop;
        for (; *l; l++)
        {
            tb_thread_wait(*l, -1, tb_null);
            tb_thread_exit(*l);
        }
    }
#endif

    // exit aicp
    if (aicp) tb_aicp_exit(aicp);
    return 0;
}