Ejemplo n.º 1
0
tb_void_t tb_lo_scheduler_resume(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);

    // remove it from the suspend coroutines
    tb_list_entry_remove(&scheduler->coroutines_suspend, &coroutine->entry);

    // make it as ready
    tb_lo_scheduler_make_ready(scheduler, coroutine);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
tb_void_t gb_mesh_face_list_kill(gb_mesh_face_list_ref_t list, gb_mesh_face_ref_t face)
{
    // check
    gb_mesh_face_list_impl_t* impl = (gb_mesh_face_list_impl_t*)list;
    tb_assert_and_check_return(impl && impl->pool && face);

#ifdef __gb_debug__
    // check
    tb_assert_abort(face->id);

    // clear id
    face->id = 0;
#endif

    // remove from the face list
    tb_list_entry_remove(&impl->head, &face->entry);

    // exit it
    tb_fixed_pool_free(impl->pool, face);
}
Ejemplo n.º 5
0
tb_size_t tb_list_remove(tb_list_ref_t self, tb_size_t itor)
{
    // check
    tb_list_t* list = (tb_list_t*)self;
    tb_assert_and_check_return_val(list && list->pool && itor, 0);

    // the node
    tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor;
    tb_assert_and_check_return_val(node, tb_iterator_tail(self));

    // the next node
    tb_list_entry_ref_t next = tb_list_entry_next(node);

    // remove node
    tb_list_entry_remove(&list->head, node);

    // free node
    tb_fixed_pool_free(list->pool, node);
    
    // the next node
    return (tb_size_t)next;
}
Ejemplo n.º 6
0
static tb_bool_t tb_transfer_task_done(tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_hize_t save, tb_size_t rate, tb_cpointer_t priv)
{
    // the task
    tb_transfer_task_t* task = (tb_transfer_task_t*)priv;
    tb_assert_and_check_return_val(task && task->transfer, tb_false);

    // the pool
    tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)task->pool;
    tb_assert_and_check_return_val(impl, tb_false);

    // trace
    tb_trace_d("task[%p]: done: %llu bytes, rate: %lu bytes/s, state: %s", task, save, rate, tb_state_cstr(state));

    // done func
    tb_bool_t ok = task->func? task->func(state, offset, size, save, rate, task->priv) : tb_true; 

    // failed, killed or closed?
    if (state != TB_STATE_OK && state != TB_STATE_PAUSED)
    {
        // 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);
        task = tb_null;

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

    // ok?
    return ok;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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;
}