示例#1
0
文件: face_list.c 项目: cdrr/gbox
gb_mesh_face_ref_t gb_mesh_face_list_make(gb_mesh_face_list_ref_t list)
{
    // check
    gb_mesh_face_list_impl_t* impl = (gb_mesh_face_list_impl_t*)list;
    tb_assert_and_check_return_val(impl && impl->pool, tb_null);

    // make it
    gb_mesh_face_ref_t face = (gb_mesh_face_ref_t)tb_fixed_pool_malloc0(impl->pool);
    tb_assert_and_check_return_val(face, tb_null);

#ifdef __gb_debug__
    // init id
    face->id = ++impl->id;

    // save list
    face->list = (tb_pointer_t)list;
#endif

    // insert to the face list
    switch (impl->order)
    {
    case GB_MESH_ORDER_INSERT_HEAD:
        tb_list_entry_insert_head(&impl->head, &face->entry);
        break;
    case GB_MESH_ORDER_INSERT_TAIL:
    default:
        tb_list_entry_insert_tail(&impl->head, &face->entry);
        break;
    }

    // ok
    return face;
}
示例#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
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_void_t tb_transfer_task_exit(tb_transfer_pool_impl_t* impl, tb_transfer_task_t* task)
{
    // check
    tb_assert_and_check_return(impl && impl->pool && task);

    // trace
    tb_trace_d("task[%p]: exit", task);

    // append task to the idle list
    tb_list_entry_insert_tail(&impl->idle, &task->entry);
}
示例#4
0
文件: scheduler.c 项目: ljx0305/tbox
static tb_void_t tb_lo_scheduler_make_suspend(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
    // check
    tb_assert(scheduler && coroutine);
    tb_assert(tb_lo_core_state(coroutine) == TB_STATE_SUSPEND);

    // trace
    tb_trace_d("suspend coroutine(%p)", coroutine);

    // remove this coroutine from the ready coroutines
    tb_list_entry_remove(&scheduler->coroutines_ready, &coroutine->entry);

    // append this coroutine to suspend coroutines
    tb_list_entry_insert_tail(&scheduler->coroutines_suspend, &coroutine->entry);
}
示例#5
0
文件: thread_pool.c 项目: luxuan/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * worker implementation
 */
static tb_bool_t tb_thread_pool_worker_walk_pull(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value, tb_bool_t* is_break)
{
    // the worker pull
    tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)value;
    tb_assert_abort(worker && worker->jobs && worker->stats && is_break);

    // full?
    if (worker->pull >= TB_THREAD_POOL_JOBS_PULL_TIME_MAXN)
    {
        // break it
        *is_break = tb_true;
        return tb_false;
    }

    // the job
    tb_thread_pool_job_t* job = (tb_thread_pool_job_t*)item;
    tb_assert_abort(job);

    // the pool
    tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool;
    tb_assert_abort(impl);

    // append the job to the pending jobs
    tb_list_entry_insert_tail(&impl->jobs_pending, &job->entry);  

    // append the job to the working jobs
    tb_vector_insert_tail(worker->jobs, job);   

    // computate the job average time 
    tb_size_t average_time = 200;
    if (tb_hash_map_size(worker->stats))
    {
        tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)tb_hash_map_get(worker->stats, job->task.done);
        if (stats && stats->done_count) average_time = (tb_size_t)(stats->total_time / stats->done_count);
    }

    // update the pull time
    worker->pull += average_time;

    // trace
    tb_trace_d("worker[%lu]: pull: task[%p:%s] from %s", worker->id, job->task.done, job->task.name, iterator == tb_list_entry_itor(&impl->jobs_waiting)? "waiting" : "urgent");

    // remove the job from the waiting or urgent jobs
    return tb_true;
}
示例#6
0
文件: scheduler.c 项目: ljx0305/tbox
static tb_void_t tb_lo_scheduler_make_dead(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
    // check
    tb_assert(scheduler && coroutine);
    tb_assert(tb_lo_core_state(coroutine) == TB_STATE_END);

    // trace
    tb_trace_d("finish coroutine(%p)", coroutine);

    // free the user private data first
    if (coroutine->free) coroutine->free(coroutine->priv);

    // remove this coroutine from the ready coroutines
    tb_list_entry_remove(&scheduler->coroutines_ready, &coroutine->entry);

    // append this coroutine to dead coroutines
    tb_list_entry_insert_tail(&scheduler->coroutines_dead, &coroutine->entry);
}
示例#7
0
文件: scheduler.c 项目: ljx0305/tbox
static tb_void_t tb_lo_scheduler_make_ready(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_t* coroutine)
{
    // check
    tb_assert(scheduler && coroutine);

    // mark ready state
    tb_lo_core_state_set(coroutine, TB_STATE_READY);

    // insert this coroutine to ready coroutines 
    if (scheduler->running)
    { 
        // .. -> coroutine(inserted) -> running -> ..
        tb_list_entry_insert_prev(&scheduler->coroutines_ready, &scheduler->running->entry, &coroutine->entry);
    }
    else
    {
        // .. last -> coroutine(inserted)
        tb_list_entry_insert_tail(&scheduler->coroutines_ready, &coroutine->entry);
    }
}
示例#8
0
tb_bool_t tb_fixed_pool_free_(tb_fixed_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__)
{ 
    // check
    tb_fixed_pool_impl_t* impl = (tb_fixed_pool_impl_t*)pool;
    tb_assert_and_check_return_val(impl, tb_false);

    // done
    tb_bool_t ok = tb_false;
    do
    {
        // check
        tb_assertf_and_check_break(impl->item_count, "double free data: %p", data);

        // find the slot 
        tb_fixed_pool_slot_t* slot = tb_fixed_pool_slot_find(impl, data);
        tb_assertf_and_check_break(slot, "the data: %p not belong to pool: %p", data, pool);
        tb_assert_and_check_break(slot->pool);

        // the slot is full?
        tb_bool_t full = tb_static_fixed_pool_full(slot->pool);

        // done exit
        if (impl->func_exit) impl->func_exit(data, impl->func_priv);

        // free it
        if (!tb_static_fixed_pool_free(slot->pool, data __tb_debug_args__)) break;

        // not the current slot?
        if (slot != impl->current_slot)
        {
            // is full? move the slot to the partial slots
            if (full)
            {
                tb_list_entry_remove(&impl->full_slots, &slot->entry);
                tb_list_entry_insert_tail(&impl->partial_slots, &slot->entry);
            }
            // is null? exit the slot
            else if (tb_static_fixed_pool_null(slot->pool))
            {
                tb_list_entry_remove(&impl->partial_slots, &slot->entry);
                tb_fixed_pool_slot_exit(impl, slot);
            }
        }

        // update the item count
        impl->item_count--;
 
        // ok
        ok = tb_true;

    } while (0);

    // failed? dump it
#ifdef __tb_debug__
    if (!ok) 
    {
        // trace
        tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_);

        // dump data
        tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[fixed_pool]: [error]: ");

        // abort
        tb_abort();
    }
#endif

    // ok?
    return ok;
}
示例#9
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;
}
示例#10
0
tb_bool_t tb_transfer_pool_done(tb_transfer_pool_ref_t pool, tb_char_t const* iurl, tb_char_t const* ourl, tb_hize_t offset, tb_size_t rate, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv)
{
    // check
    tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool;
    tb_assert_and_check_return_val(impl && impl->aicp && iurl && ourl, tb_false);
    
    // enter
    tb_spinlock_enter(&impl->lock);

    // done
    tb_bool_t               ok = tb_false;
    tb_transfer_task_t*     task = tb_null;
    do
    {
        // check 
        tb_check_break(TB_STATE_OK == tb_atomic_get(&impl->state));

        // too many tasks?
        if (tb_list_entry_size(&impl->work) >= impl->maxn)
        {
            // trace
            tb_trace_e("too many tasks, done task: %s => %s failed!", iurl, ourl);
            break;
        }

        // init task
        task = tb_transfer_task_init(impl, done, ctrl, priv);
        tb_assert_and_check_break(task && task->transfer);

        // init transfer stream
        if (!tb_async_transfer_init_istream_from_url(task->transfer, iurl)) break;
        if (!tb_async_transfer_init_ostream_from_url(task->transfer, ourl)) break;

        // init transfer rate
        tb_async_transfer_limitrate(task->transfer, rate);

        // check
        tb_assert_and_check_break(impl->pool);

        // append to the work list
        tb_list_entry_insert_tail(&impl->work, &task->entry);

        // ok
        ok = tb_true;

    } while (0);

    // trace
    tb_trace_d("done: task: %p, %s => %s, work: %lu, idle: %lu, state: %s", task, iurl, ourl, tb_list_entry_size(&impl->work), tb_list_entry_size(&impl->idle), ok? "ok" : "no");

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

    // leave
    tb_spinlock_leave(&impl->lock);

    // ok? done it
    if (ok && task && task->transfer)
    {
        // done
        if (!tb_async_transfer_open_done(task->transfer, 0, tb_transfer_task_done, task))
        {
            // enter
            tb_spinlock_enter(&impl->lock);

            // remove task from the work list
            tb_list_entry_remove(&impl->work, &task->entry);

            // exit task
            tb_transfer_task_exit(impl, task);

            // leave
            tb_spinlock_leave(&impl->lock);

            // failed
            ok = tb_false;
        }
    }

    // ok?
    return ok;
}
示例#11
0
文件: thread_pool.c 项目: luxuan/tbox
static tb_thread_pool_job_t* tb_thread_pool_jobs_post_task(tb_thread_pool_impl_t* impl, tb_thread_pool_task_t const* task, tb_size_t* post_size)
{
    // check
    tb_assert_and_check_return_val(impl && task && task->done && post_size, tb_null);

    // done
    tb_bool_t               ok = tb_false;
    tb_thread_pool_job_t*   job = tb_null;
    do
    {
        // check
        tb_assert_and_check_break(tb_list_entry_size(&impl->jobs_waiting) + tb_list_entry_size(&impl->jobs_urgent) + 1 < TB_THREAD_POOL_JOBS_WAITING_MAXN);

        // make job
        job = (tb_thread_pool_job_t*)tb_fixed_pool_malloc0(impl->jobs_pool);
        tb_assert_and_check_break(job);

        // init job
        job->refn   = 1;
        job->state  = TB_STATE_WAITING;
        job->task   = *task;

        // non-urgent job? 
        if (!task->urgent)
        {
            // post to the waiting jobs
            tb_list_entry_insert_tail(&impl->jobs_waiting, &job->entry);
        }
        else
        {
            // post to the urgent jobs
            tb_list_entry_insert_tail(&impl->jobs_urgent, &job->entry);
        }

        // the waiting jobs count
        tb_size_t jobs_waiting_count = tb_list_entry_size(&impl->jobs_waiting) + tb_list_entry_size(&impl->jobs_urgent);
        tb_assert_and_check_break(jobs_waiting_count);

        // update the post size
        if (*post_size < impl->worker_size) (*post_size)++;

        // trace
        tb_trace_d("task[%p:%s]: post: %lu: ..", task->done, task->name, *post_size);

        // init them if the workers have been not inited
        if (impl->worker_size < jobs_waiting_count)
        {
            tb_size_t i = impl->worker_size;
            tb_size_t n = tb_min(jobs_waiting_count, impl->worker_maxn);
            for (; i < n; i++)
            {
                // the worker 
                tb_thread_pool_worker_t* worker = &impl->worker_list[i];

                // clear worker
                tb_memset(worker, 0, sizeof(tb_thread_pool_worker_t));

                // init worker
                worker->id          = i;
                worker->pool        = (tb_thread_pool_ref_t)impl;
                worker->loop        = tb_thread_init(__tb_lstring__("thread_pool"), tb_thread_pool_worker_loop, worker, impl->stack);
                tb_assert_and_check_continue(worker->loop);
            }

            // update the worker size
            impl->worker_size = i;
        }

        // ok
        ok = tb_true;
    
    } while (0);

    // failed?
    if (!ok)
    {
        // exit it
        tb_fixed_pool_free(impl->jobs_pool, job);
        job = tb_null;
    }

    // ok?
    return job;
}