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); }
/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }
/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }
tb_size_t tb_hash_set_size(tb_hash_set_ref_t self) { return tb_hash_map_size((tb_hash_map_ref_t)self); }
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); } } } } }
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; }