예제 #1
0
파일: scheduler.c 프로젝트: ljx0305/tbox
static __tb_inline__ tb_lo_coroutine_t* tb_lo_scheduler_next_ready(tb_lo_scheduler_t* scheduler)
{
    // check
    tb_assert(scheduler && tb_list_entry_size(&scheduler->coroutines_ready));

    // get the next entry 
    tb_list_entry_ref_t entry_next = scheduler->running? tb_list_entry_next(&scheduler->running->entry) : tb_list_entry_head(&scheduler->coroutines_ready);
    tb_assert(entry_next);

    // is list header? skip it and get the first entry
    if (entry_next == (tb_list_entry_ref_t)&scheduler->coroutines_ready)
        entry_next = tb_list_entry_next(entry_next);

    // get the next ready coroutine
    return (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_ready, entry_next);
}
예제 #2
0
파일: list_entry.c 프로젝트: ljx0305/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * main
 */
tb_int_t tb_demo_container_list_entry_main(tb_int_t argc, tb_char_t** argv)
{
    // init the entries
    tb_demo_entry_t entries[12] = 
    {
        {{0}, 0}
    ,   {{0}, 1}
    ,   {{0}, 2}
    ,   {{0}, 3}
    ,   {{0}, 4}
    ,   {{0}, 5}
    ,   {{0}, 6}
    ,   {{0}, 7}
    ,   {{0}, 8}
    ,   {{0}, 9}
    ,   {{0}, 10}
    ,   {{0}, 11}
    };

    // init the list
    tb_list_entry_head_t list;
    tb_list_entry_init(&list, tb_demo_entry_t, entry, tb_demo_entry_copy);

    // insert entries
    tb_list_entry_insert_tail(&list, &entries[5].entry);
    tb_list_entry_insert_tail(&list, &entries[6].entry);
    tb_list_entry_insert_tail(&list, &entries[7].entry);
    tb_list_entry_insert_tail(&list, &entries[8].entry);
    tb_list_entry_insert_tail(&list, &entries[9].entry);
    tb_list_entry_insert_head(&list, &entries[4].entry);
    tb_list_entry_insert_head(&list, &entries[3].entry);
    tb_list_entry_insert_head(&list, &entries[2].entry);
    tb_list_entry_insert_head(&list, &entries[1].entry);
    tb_list_entry_insert_head(&list, &entries[0].entry);

    // the entry
    tb_demo_entry_t* entry = (tb_demo_entry_t*)tb_list_entry(&list, &entries[5].entry);
    tb_trace_i("entry: %lu", entry->data);
    tb_trace_i("");

    // walk it
    tb_trace_i("insert: %lu", tb_list_entry_size(&list));
    tb_for_all_if(tb_demo_entry_t*, item0, tb_list_entry_itor(&list), item0)
    {
        tb_trace_i("%lu", item0->data);
    }
예제 #3
0
파일: scheduler.c 프로젝트: ljx0305/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * private implementation
 */
static tb_void_t tb_lo_scheduler_free(tb_list_entry_head_ref_t coroutines)
{
    // check
    tb_assert(coroutines);

    // free all coroutines
    while (tb_list_entry_size(coroutines))
    {
        // get the next entry from head
        tb_list_entry_ref_t entry = tb_list_entry_head(coroutines);
        tb_assert(entry);

        // remove it from the ready coroutines
        tb_list_entry_remove_head(coroutines);

        // exit this coroutine
        tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(coroutines, entry));
    }
}
예제 #4
0
파일: scheduler.c 프로젝트: ljx0305/tbox
tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free)
{
    // check
    tb_assert(func);

    // done
    tb_bool_t           ok = tb_false;
    tb_lo_coroutine_t*  coroutine = tb_null;
    do
    {
        // trace
        tb_trace_d("start ..");

        // get the current scheduler
        if (!scheduler) scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_();
        tb_assert_and_check_break(scheduler);

        // have been stopped? do not continue to start new coroutines
        tb_check_break(!scheduler->stopped);

        // reuses dead coroutines in init function
        if (tb_list_entry_size(&scheduler->coroutines_dead))
        {
            // get the next entry from head
            tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead);
            tb_assert_and_check_break(entry);

            // remove it from the ready coroutines
            tb_list_entry_remove_head(&scheduler->coroutines_dead);

            // get the dead coroutine
            coroutine = (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry);

            // reinit this coroutine
            tb_lo_coroutine_reinit(coroutine, func, priv, free);
        }

        // init coroutine
        if (!coroutine) coroutine = tb_lo_coroutine_init((tb_lo_scheduler_ref_t)scheduler, func, priv, free);
        tb_assert_and_check_break(coroutine);

        // ready coroutine
        tb_lo_scheduler_make_ready(scheduler, coroutine);

        // the dead coroutines is too much? free some coroutines
        while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN)
        {
            // get the next entry from head
            tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead);
            tb_assert(entry);

            // remove it from the ready coroutines
            tb_list_entry_remove_head(&scheduler->coroutines_dead);

            // exit this coroutine
            tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry));
        }

        // ok
        ok = tb_true;

    } while (0);

    // trace
    tb_trace_d("start %s", ok? "ok" : "no");

    // ok?
    return ok;
}
예제 #5
0
tb_pointer_t tb_fixed_pool_malloc_(tb_fixed_pool_ref_t pool __tb_debug_decl__)
{
    // check
    tb_fixed_pool_impl_t* impl = (tb_fixed_pool_impl_t*)pool;
    tb_assert_and_check_return_val(impl, tb_null);

    // done
    tb_bool_t       ok = tb_false;
    tb_pointer_t    data = tb_null;
    do
    {
        // no current slot or the current slot is full? update the current slot
        if (!impl->current_slot || tb_static_fixed_pool_full(impl->current_slot->pool))
        {
            // move the current slot to the full slots if exists
            if (impl->current_slot) tb_list_entry_insert_tail(&impl->full_slots, &impl->current_slot->entry);

            // clear the current slot
            impl->current_slot = tb_null;

            // attempt to get a slot from the partial slots
            if (!tb_list_entry_is_null(&impl->partial_slots))
            {
                // the head entry
                tb_list_entry_ref_t entry = tb_list_entry_head(&impl->partial_slots);
                tb_assert_and_check_break(entry);

                // the head slot
                impl->current_slot = (tb_fixed_pool_slot_t*)tb_list_entry(&impl->partial_slots, entry);
                tb_assert_and_check_break(impl->current_slot);

                // remove this slot from the partial slots
                tb_list_entry_remove(&impl->partial_slots, entry);
            }
            // make a new slot
            else impl->current_slot = tb_fixed_pool_slot_init(impl);
        }

        // check
        tb_assert_and_check_break(impl->current_slot && impl->current_slot->pool);
        tb_assert_and_check_break(!tb_static_fixed_pool_full(impl->current_slot->pool));

        // make data from the current slot
        data = tb_static_fixed_pool_malloc(impl->current_slot->pool __tb_debug_args__);
        tb_assert_and_check_break(data);
        
        // done init
        if (impl->func_init && !impl->func_init(data, impl->func_priv)) break;

        // update the item count
        impl->item_count++;

        // ok
        ok = tb_true;

    } while (0);

    // failed?
    if (!ok)
    {
        // exit data
        if (data && impl->current_slot && impl->current_slot->pool) 
            tb_static_fixed_pool_free(impl->current_slot->pool, data __tb_debug_args__);
        data = tb_null;
    }

    // check
    tb_assertf_abort(data, "malloc(%lu) failed!", impl->item_size);

    // ok?
    return data;
}
예제 #6
0
static tb_transfer_task_t* tb_transfer_task_init(tb_transfer_pool_impl_t* impl, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv)
{
    // check
    tb_assert_and_check_return_val(impl, tb_null);

    // done
    tb_bool_t           ok = tb_false;
    tb_transfer_task_t* task = tb_null;
    do
    {
        // init task pool
        if (!impl->pool) impl->pool = tb_fixed_pool_init(tb_null, (impl->maxn >> 4) + 16, sizeof(tb_transfer_task_t), tb_null, tb_null, tb_null);
        tb_assert_and_check_break(impl->pool);

        // init task from the idle list first
        if (tb_list_entry_size(&impl->idle))
        {
            // get the head entry
            tb_list_entry_ref_t entry = tb_list_entry_head(&impl->idle);
            tb_assert_and_check_break(entry);

            // the task
            task = (tb_transfer_task_t*)tb_list_entry(&impl->idle, entry);
            tb_assert_and_check_break(task);

            // remove the last task
            tb_list_entry_remove(&impl->idle, entry);

            // check
            tb_assert_and_check_break(task->transfer);
        }
        // init task from the task pool
        else
        {
            // make task
            task = (tb_transfer_task_t*)tb_fixed_pool_malloc0(impl->pool);
            tb_assert_and_check_break(task);

            // init transfer
            task->transfer = tb_async_transfer_init(impl->aicp, tb_true);
            tb_assert_and_check_break(task->transfer);
        }

        // init ctrl
        if (ctrl && !tb_async_transfer_ctrl(task->transfer, ctrl, priv)) break;

        // init task
        task->func = done;
        task->priv = priv;
        task->pool = impl;

        // ok
        ok = tb_true;

    } while (0);

    // failed?
    if (!ok)
    {
        // exit it
        if (task) tb_transfer_task_exit(impl, task);
        task = tb_null;
    }

    // ok?
    return task;
}