Пример #1
0
tb_size_t tb_object_dictionary_size(tb_object_ref_t object)
{
    // check
    tb_object_dictionary_t* dictionary = tb_object_dictionary_cast(object);
    tb_assert_and_check_return_val(dictionary && dictionary->hash, 0);

    // size
    return tb_hash_map_size(dictionary->hash);
}
Пример #2
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_bool_t tb_aiop_rtor_select_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
{
    // check
    tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor;
    tb_assert_and_check_return_val(impl && rtor->aiop && aioo && aioo->sock, tb_false);

    // the aiop
    tb_aiop_impl_t* aiop = rtor->aiop;
    tb_assert_and_check_return_val(aiop, tb_false);

    // check size
    tb_spinlock_enter(&impl->lock.hash);
    tb_size_t size = tb_hash_map_size(impl->hash);
    tb_spinlock_leave(&impl->lock.hash);
    tb_assert_and_check_return_val(size < FD_SETSIZE, tb_false);

    // add sock => aioo
    tb_bool_t ok = tb_false;
    tb_spinlock_enter(&impl->lock.hash);
    if (impl->hash) 
    {
        tb_hash_map_insert(impl->hash, aioo->sock, aioo);
        ok = tb_true;
    }
    tb_spinlock_leave(&impl->lock.hash);
    tb_assert_and_check_return_val(ok, tb_false);

    // the fd
    tb_long_t fd = ((tb_long_t)aioo->sock) - 1;

    // the code
    tb_size_t code = aioo->code;

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

    // update fd max
    if (fd > (tb_long_t)impl->sfdm) impl->sfdm = (tb_size_t)fd;
    
    // init fds
    if (code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_ACPT)) FD_SET(fd, &impl->rfdi);
    if (code & (TB_AIOE_CODE_SEND | TB_AIOE_CODE_CONN)) FD_SET(fd, &impl->wfdi);

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

    // spak it
    if (aiop->spak[0] && code) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);

    // ok?
    return ok;
}
Пример #3
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * 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;
}
Пример #4
0
tb_size_t tb_hash_set_size(tb_hash_set_ref_t self)
{
    return tb_hash_map_size((tb_hash_map_ref_t)self);
}
Пример #5
0
tb_void_t tb_hash_map_dump(tb_hash_map_ref_t hash_map)
{
    // check
    tb_hash_map_impl_t* impl = (tb_hash_map_impl_t*)hash_map;
    tb_assert_and_check_return(impl && impl->hash_list);

    // the step
    tb_size_t step = impl->element_name.size + impl->element_data.size;
    tb_assert_and_check_return(step);

    // trace
    tb_trace_i("");
    tb_trace_i("hash_map: size: %lu", tb_hash_map_size(hash_map));

    // done
    tb_size_t i = 0;
    tb_char_t name[4096];
    tb_char_t data[4096];
    for (i = 0; i < impl->hash_size; i++)
    {
        // the list
        tb_hash_map_item_list_t* list = impl->hash_list[i];
        if (list)
        {
            // trace
            tb_trace_i("buck[%u]: size: %u, maxn: %u", i, list->size, list->maxn);

            // done 
            tb_size_t j = 0;
            for (j = 0; j < list->size; j++)
            {
                // the item
                tb_byte_t const* item = ((tb_byte_t*)&list[1]) + j * step;

                // the item name
                tb_pointer_t element_name = impl->element_name.data(&impl->element_name, item);

                // the item data
                tb_pointer_t element_data = impl->element_data.data(&impl->element_data, item + impl->element_name.size);

                // trace
                if (impl->element_name.cstr && impl->element_data.cstr)
                {
                    tb_trace_i("    %s => %s", impl->element_name.cstr(&impl->element_name, element_name, name, sizeof(name)), impl->element_data.cstr(&impl->element_data, element_data, data, sizeof(data)));
                }
                else if (impl->element_name.cstr) 
                {
                    tb_trace_i("    %s => %p", impl->element_name.cstr(&impl->element_name, element_name, name, sizeof(name)), element_data);
                }
                else if (impl->element_data.cstr) 
                {
                    tb_trace_i("    %x => %p", element_name, impl->element_data.cstr(&impl->element_data, element_data, data, sizeof(data)));
                }
                else 
                {
                    tb_trace_i("    %p => %p", element_name, element_data);
                }
            }
        }
    }
}
Пример #6
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;
}