Exemple #1
0
tb_void_t tb_timer_task_exit(tb_timer_ref_t timer, tb_timer_task_ref_t task)
{
    // check
    tb_timer_impl_t*         impl = (tb_timer_impl_t*)timer;
    tb_timer_task_impl_t*    task_impl = (tb_timer_task_impl_t*)task;
    tb_assert_and_check_return(impl && impl->pool && task_impl);

    // trace
    tb_trace_d("exit: when: %lld, period: %u, refn: %u", task_impl->when, task_impl->period, task_impl->refn);

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

    // remove it?
    if (task_impl->refn > 1)
    {
        // refn--
        task_impl->refn--;

        // cancel task 
        task_impl->func      = tb_null;
        task_impl->priv      = tb_null;
        task_impl->repeat    = 0;
    }
    // remove it from pool directly if the task_impl have been expired 
    else tb_fixed_pool_free(impl->pool, task_impl);

    // leave
    tb_spinlock_leave(&impl->lock);
}
Exemple #2
0
tb_void_t tb_aico_exit(tb_aico_ref_t aico)
{
    // check
    tb_aico_impl_t* impl = (tb_aico_impl_t*)aico;
    tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp;
    tb_assert_and_check_return(impl && aicp_impl && aicp_impl->pool);

    // wait closing?
    tb_size_t tryn = 15;
    while (tb_atomic_get(&impl->state) != TB_STATE_CLOSED && tryn--)
    {
        // trace
        tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: wait: ..", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state)));
    
        // wait some time
        tb_msleep(200);
    }

    // check
    tb_assert_abort(tb_atomic_get(&impl->state) == TB_STATE_CLOSED);
    tb_check_return(tb_atomic_get(&impl->state) == TB_STATE_CLOSED);

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

    // trace
    tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: ok", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state)));
    
    // free it
    tb_fixed_pool_free(aicp_impl->pool, aico);

    // leave 
    tb_spinlock_leave(&aicp_impl->lock);
}
Exemple #3
0
Fichier : aiop.c Projet : cdrr/tbox
static tb_void_t tb_aiop_aioo_exit(tb_aiop_impl_t* impl, tb_aioo_ref_t aioo)
{
    // check
    tb_assert_and_check_return(impl && impl->pool);

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

    // exit aioo
    if (aioo) tb_fixed_pool_free(impl->pool, aioo);

    // leave 
    tb_spinlock_leave(&impl->lock);
}
Exemple #4
0
static tb_bool_t tb_thread_pool_worker_walk_clean(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
    // the worker pull
    tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)value;
    tb_assert_abort(worker && worker->jobs);

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

    // the job state
    tb_size_t state = tb_atomic_get(&job->state);

    // finished or killed? remove it
    tb_bool_t ok = tb_false;
    if (state == TB_STATE_FINISHED || state == TB_STATE_KILLED)
    {
        // trace
        tb_trace_d("worker[%lu]: remove: task[%p:%s] from pending", worker->id, job->task.done, job->task.name);

        // exit the job
        if (job->task.exit) job->task.exit((tb_thread_pool_worker_ref_t)worker, job->task.priv);

        // remove it from the pending jobs
        ok = tb_true;

        // refn--
        if (job->refn > 1) job->refn--;
        // remove it from pool directly
        else 
        {
            // the pool
            tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool;
            tb_assert_abort(impl);

            // remove it from the jobs pool
            tb_fixed_pool_free(impl->jobs_pool, job);
        }
    }

    // remove it?
    return ok;
}
Exemple #5
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);
}
Exemple #6
0
static tb_void_t tb_demo_spider_task_exit(tb_demo_spider_task_t* task)
{
    // check
    tb_assert_and_check_return(task);

    // the spider 
    tb_demo_spider_t* spider = task->spider;
    tb_assert_and_check_return(spider);

    // trace
    tb_trace_d("task: exit: %s", task->iurl);

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

    // exit task
    if (spider->pool) tb_fixed_pool_free(spider->pool, task);

    // leave
    tb_spinlock_leave(&spider->lock);
}
Exemple #7
0
tb_void_t tb_thread_pool_task_exit(tb_thread_pool_ref_t pool, tb_thread_pool_task_ref_t task)
{
    // check
    tb_thread_pool_impl_t*  impl = (tb_thread_pool_impl_t*)pool;
    tb_thread_pool_job_t*   job = (tb_thread_pool_job_t*)task;
    tb_assert_and_check_return(impl && job);

    // kill it first
    tb_thread_pool_task_kill(pool, task);

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

    // refn--
    if (job->refn > 1) job->refn--;
    // remove it from pool directly
    else tb_fixed_pool_free(impl->jobs_pool, job);

    // leave
    tb_spinlock_leave(&impl->lock);
}
Exemple #8
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;
}
Exemple #9
0
tb_void_t gb_mesh_edge_list_kill(gb_mesh_edge_list_ref_t list, gb_mesh_edge_ref_t edge)
{
    // check
    gb_mesh_edge_list_impl_t* impl = (gb_mesh_edge_list_impl_t*)list;
    tb_assert_and_check_return(impl && impl->pool && edge);

    // make sure the edge points to the first half-edge
    if (edge->sym < edge) edge = edge->sym;

#ifdef __gb_debug__
    // check
    tb_assert(edge->id && edge->sym->id);

    // clear id
    edge->id        = 0;
    edge->sym->id   = 0;
#endif

    // remove it from the list
    gb_mesh_edge_remove_done(edge);

    // exit it
    tb_fixed_pool_free(impl->pool, edge);
}
Exemple #10
0
tb_bool_t tb_timer_spak(tb_timer_ref_t timer)
{
    // check
    tb_timer_impl_t* impl = (tb_timer_impl_t*)timer;
    tb_assert_and_check_return_val(impl && impl->pool && impl->heap, tb_false);

    // stoped?
    tb_check_return_val(!tb_atomic_get(&impl->stop), tb_false);

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

    // done
    tb_bool_t               ok = tb_false;
    tb_timer_task_func_t    func = tb_null;
    tb_cpointer_t           priv = tb_null;
    tb_bool_t               killed = tb_false;
    do
    {
        // empty? 
        if (!tb_heap_size(impl->heap))
        {
            ok = tb_true;
            break;
        }

        // the top task
        tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)tb_heap_top(impl->heap);
        tb_assert_and_check_break(task_impl);

        // check refn
        tb_assert(task_impl->refn);

        // the now
        tb_hong_t now = tb_timer_now(impl);

        // timeout?
        if (task_impl->when <= now)
        {
            // pop it
            tb_heap_pop(impl->heap);

            // save func and data for calling it later
            func = task_impl->func;
            priv = task_impl->priv;

            // killed?
            killed = task_impl->killed? tb_true : tb_false;

            // repeat?
            if (task_impl->repeat)
            {
                // update when
                task_impl->when = now + task_impl->period;

                // continue task_impl
                tb_heap_put(impl->heap, task_impl);
            }
            else 
            {
                // refn--
                if (task_impl->refn > 1) task_impl->refn--;
                // remove it from pool directly
                else tb_fixed_pool_free(impl->pool, task_impl);
            }
        }

        // ok
        ok = tb_true;

    } while (0);

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

    // done func
    if (func) func(killed, priv);

    // ok?
    return ok;
}
Exemple #11
0
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;
}
Exemple #12
0
static tb_bool_t tb_thread_pool_worker_walk_pull_and_clean(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
    // the worker pull
    tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)value;
    tb_assert_abort(worker && worker->jobs && worker->stats);

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

    // the job state
    tb_size_t state = tb_atomic_get(&job->state);

    // waiting and non-full? pull it
    tb_bool_t ok = tb_false;
    if (state == TB_STATE_WAITING && worker->pull < TB_THREAD_POOL_JOBS_PULL_TIME_MAXN)
    {
        // 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 pending", worker->id, job->task.done, job->task.name);
    }
    // finished or killed? remove it
    else if (state == TB_STATE_FINISHED || state == TB_STATE_KILLED)
    {
        // trace
        tb_trace_d("worker[%lu]: remove: task[%p:%s] from pending", worker->id, job->task.done, job->task.name);

        // exit the job
        if (job->task.exit) job->task.exit((tb_thread_pool_worker_ref_t)worker, job->task.priv);

        // remove it from the waiting or urgent jobs
        ok = tb_true;

        // refn--
        if (job->refn > 1) job->refn--;
        // remove it from pool directly
        else 
        {
            // the pool
            tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool;
            tb_assert_abort(impl);

            // remove it from the jobs pool
            tb_fixed_pool_free(impl->jobs_pool, job);
        }
    }

    // remove it?
    return ok;
}