예제 #1
0
파일: aiop.c 프로젝트: cdrr/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * aioo
 */
static tb_aioo_ref_t tb_aiop_aioo_init(tb_aiop_impl_t* impl, tb_socket_ref_t sock, tb_size_t code, tb_cpointer_t priv)
{
    // check
    tb_assert_and_check_return_val(impl && impl->pool, tb_null);

    // enter 
    tb_spinlock_enter(&impl->lock);

    // make aioo
    tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)tb_fixed_pool_malloc0(impl->pool);

    // init aioo
    if (aioo)
    {
        aioo->code = code;
        aioo->priv = priv;
        aioo->sock = sock;
    }

    // leave 
    tb_spinlock_leave(&impl->lock);
    
    // ok?
    return (tb_aioo_ref_t)aioo;
}
예제 #2
0
파일: aico.c 프로젝트: 1060460048/tbox
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_aico_ref_t tb_aico_init(tb_aicp_ref_t aicp)
{
    // check
    tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)aicp;
    tb_assert_and_check_return_val(aicp_impl && aicp_impl->pool, tb_null);

    // enter 
    tb_spinlock_enter(&aicp_impl->lock);

    // make aico
    tb_aico_impl_t* aico = (tb_aico_impl_t*)tb_fixed_pool_malloc0(aicp_impl->pool);

    // init aico
    if (aico)
    {
        aico->aicp      = aicp;
        aico->type      = TB_AICO_TYPE_NONE;
        aico->handle    = tb_null;
        aico->state     = TB_STATE_CLOSED;

        // init timeout 
        tb_size_t i = 0;
        tb_size_t n = tb_arrayn(aico->timeout);
        for (i = 0; i < n; i++) aico->timeout[i] = -1;
    }

    // leave 
    tb_spinlock_leave(&aicp_impl->lock);
    
    // ok?
    return (tb_aico_ref_t)aico;
}
예제 #3
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;
}
예제 #4
0
파일: timer.c 프로젝트: 1060460048/tbox
tb_timer_task_ref_t tb_timer_task_init_at(tb_timer_ref_t timer, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_timer_task_func_t func, tb_cpointer_t priv)
{
    // check
    tb_timer_impl_t* impl = (tb_timer_impl_t*)timer;
    tb_assert_and_check_return_val(impl && impl->pool && impl->heap && func, tb_null);

    // stoped?
    tb_assert_and_check_return_val(!tb_atomic_get(&impl->stop), tb_null);

    // enter
    tb_spinlock_enter(&impl->lock);

    // make task
    tb_event_ref_t          event = tb_null;
    tb_hize_t               when_top = -1;
    tb_timer_task_impl_t*   task_impl = (tb_timer_task_impl_t*)tb_fixed_pool_malloc0(impl->pool);
    if (task_impl)
    {
        // the top when 
        if (tb_heap_size(impl->heap))
        {
            tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)tb_heap_top(impl->heap);
            if (task_impl) when_top = task_impl->when;
        }

        // init task
        task_impl->refn      = 2;
        task_impl->func      = func;
        task_impl->priv      = priv;
        task_impl->when      = when;
        task_impl->period    = period;
        task_impl->repeat    = repeat? 1 : 0;

        // add task
        tb_heap_put(impl->heap, task_impl);

        // the event
        event = impl->event;
    }

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

    // post event if the top task is changed
    if (event && task_impl && when < when_top)
        tb_event_post(event);

    // ok?
    return (tb_timer_task_ref_t)task_impl;
}
예제 #5
0
파일: edge_list.c 프로젝트: bygreencn/gbox
gb_mesh_edge_ref_t gb_mesh_edge_list_make_loop(gb_mesh_edge_list_ref_t list, tb_bool_t is_ccw)
{
    // check
    gb_mesh_edge_list_impl_t* impl = (gb_mesh_edge_list_impl_t*)list;
    tb_assert_and_check_return_val(impl && impl->pool, tb_null);

    // make it
    gb_mesh_edge_ref_t edge = (gb_mesh_edge_ref_t)tb_fixed_pool_malloc0(impl->pool);
    tb_assert_and_check_return_val(edge, tb_null);

    // the sym edge
    gb_mesh_edge_ref_t edge_sym = (gb_mesh_edge_ref_t)((tb_byte_t*)edge + impl->edge_size);

    // init edge
    edge->sym       = edge_sym;
    edge->onext     = edge_sym;
    edge->lnext     = edge;

    // init sym edge
    edge_sym->sym   = edge;
    edge_sym->onext = edge;
    edge_sym->lnext = edge_sym;

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

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

    // insert to the edge list
    switch (impl->order)
    {
    case GB_MESH_ORDER_INSERT_HEAD:
        gb_mesh_edge_insert_prev(edge, impl->head->next);
        break;
    case GB_MESH_ORDER_INSERT_TAIL:
    default:
        gb_mesh_edge_insert_prev(edge, impl->head);
        break;
    }

    // clockwise? reverse it
    return is_ccw? edge : edge_sym;
}
예제 #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;
}
예제 #7
0
파일: spider.c 프로젝트: ahnan4arch/tbox
static tb_bool_t tb_demo_spider_task_done(tb_demo_spider_t* spider, tb_char_t const* iurl, tb_bool_t* full)
{
    // check
    tb_assert_and_check_return_val(spider && iurl, tb_false);

    // killed?
    tb_check_return_val(TB_STATE_OK == tb_atomic_get(&spider->state), tb_false);

    // only for home?
    if (spider->home_only && !tb_stristr(iurl, spider->home_domain)) 
    {
        // trace
        tb_trace_d("task: done: %s: skip", iurl);
        return tb_true;
    }

    // enter
    tb_spinlock_enter(&spider->lock);

    // done
    tb_bool_t               ok = tb_false;
    tb_size_t               size = 0;
    tb_demo_spider_task_t*  task = tb_null;
    tb_bool_t               repeat = tb_false;
    do
    {
        // check
        tb_assert_and_check_break(spider->filter && spider->pool);

        // the task count
        size = tb_fixed_pool_size(spider->pool);
        
        // make the output url
        if (!tb_demo_spider_make_ourl(spider, iurl, spider->ourl, sizeof(spider->ourl) - 1)) break;

        // have been done already?
        if (!tb_bloom_filter_set(spider->filter, spider->ourl)) 
        {
            // trace
            tb_trace_d("task: size: %lu, done: %s: repeat", size, iurl);

            // ok
            ok = tb_true;
            repeat = tb_true;
            break;
        }

        // trace
        tb_trace_d("task: size: %lu, done: %s: ..", size, iurl);

        // full?
        tb_check_break(size < TB_DEMO_SPIDER_TASK_MAXN);

        // make task
        task = (tb_demo_spider_task_t*)tb_fixed_pool_malloc0(spider->pool);
        tb_assert_and_check_break(task);

        // init task
        task->spider = spider;
        tb_strlcpy(task->iurl, iurl, sizeof(task->iurl) - 1);
        tb_strlcpy(task->ourl, spider->ourl, sizeof(task->ourl) - 1);
           
        // ok 
        ok = tb_true;

    } while (0);

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

    // ok?
    if (ok && !repeat)
    {
        // done
        ok = tb_false;
        do
        {
            // check
            tb_assert_and_check_break(task);

            // killed?
            tb_check_break(TB_STATE_OK == tb_atomic_get(&spider->state));

            // repeat?
            if (tb_file_info(task->ourl, tb_null))
            {
                // trace
                tb_trace_d("task: size: %lu, done: %s: repeat", size, iurl);

                // ok
                ok = tb_true;
                repeat = tb_true;
                break;
            }

            // done task
            ok = tb_transfer_pool_done(tb_transfer_pool(), task->iurl, task->ourl, 0, spider->limited_rate, tb_demo_spider_task_save, tb_demo_spider_task_ctrl, task);
            tb_assert_and_check_break(ok);

        } while (0);
    }

    // repeat or failed?
    if (repeat || !ok)
    {
        // exit task
        if (task) tb_demo_spider_task_exit(task);
        task = tb_null;

        // failed?
        if (!full && !ok)
        {
            // trace
            tb_trace_e("task: size: %lu, done: %s: post failed", size, iurl);
        }

        // save full
        if (full) *full = size < TB_DEMO_SPIDER_TASK_MAXN? tb_false : tb_true;
    }

    // ok?
    return ok;
}
예제 #8
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;
}