tb_size_t tb_list_insert_prev(tb_list_ref_t self, tb_size_t itor, tb_cpointer_t data) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return_val(list && list->element.dupl && list->pool, 0); // full? tb_assert_and_check_return_val(tb_list_size(self) < tb_list_maxn(self), tb_iterator_tail(self)); // 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)); // make entry tb_list_entry_ref_t entry = (tb_list_entry_ref_t)tb_fixed_pool_malloc(list->pool); tb_assert_and_check_return_val(entry, tb_iterator_tail(self)); // init entry data list->element.dupl(&list->element, (tb_pointer_t)(((tb_list_entry_t*)entry) + 1), data); // insert it tb_list_entry_insert_prev(&list->head, node, entry); // ok return (tb_size_t)entry; }
static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_impl_t* impl, tb_fixed_pool_slot_t* slot) { // check tb_assert_and_check_return(impl && impl->large_pool && slot); tb_assert_and_check_return(impl->slot_list && impl->slot_count); // trace tb_trace_d("slot[%lu]: exit: size: %lu", impl->item_size, slot->size); // init the iterator tb_iterator_t iterator = tb_iterator_init_ptr((tb_pointer_t*)impl->slot_list, impl->slot_count); // find the slot from the slot list tb_size_t itor = tb_binary_find_all(&iterator, (tb_cpointer_t)slot); tb_assert_abort(itor != tb_iterator_tail(&iterator) && itor < impl->slot_count && impl->slot_list[itor]); tb_check_return(itor != tb_iterator_tail(&iterator) && itor < impl->slot_count && impl->slot_list[itor]); // remove the slot if (itor + 1 < impl->slot_count) tb_memmov_(impl->slot_list + itor, impl->slot_list + itor + 1, (impl->slot_count - itor - 1) * sizeof(tb_fixed_pool_slot_t*)); // update the slot count impl->slot_count--; // exit slot tb_large_pool_free(impl->large_pool, slot); }
/* ////////////////////////////////////////////////////////////////////////////////////// * test */ static tb_void_t tb_find_int_test() { __tb_volatile__ tb_size_t i = 0; __tb_volatile__ tb_size_t n = 1000; // init data tb_long_t* data = (tb_long_t*)tb_nalloc0(n, sizeof(tb_long_t)); tb_assert_and_check_return(data); // init iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_long(&array_iterator, data, n); // make for (i = 0; i < n; i++) data[i] = i; // find tb_size_t itor = tb_iterator_tail(iterator); tb_hong_t time = tb_mclock(); for (i = 0; i < n; i++) itor = tb_find_all(iterator, (tb_pointer_t)data[800]); time = tb_mclock() - time; // item tb_long_t item = itor != tb_iterator_tail(iterator)? (tb_long_t)tb_iterator_item(iterator, itor) : 0; // time tb_trace_i("tb_find_int_all[%ld ?= %ld]: %lld ms", item, data[800], time); // free tb_free(data); }
static tb_void_t tb_fixed_pool_slot_exit(tb_fixed_pool_t* pool, tb_fixed_pool_slot_t* slot) { // check tb_assert_and_check_return(pool && pool->large_allocator && slot); tb_assert_and_check_return(pool->slot_list && pool->slot_count); // trace tb_trace_d("slot[%lu]: exit: size: %lu", pool->item_size, slot->size); // make the iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_iterator_make_for_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count); tb_assert(iterator); // find the slot from the slot list tb_size_t itor = tb_binary_find_all(iterator, (tb_cpointer_t)slot); tb_assert(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]); tb_check_return(itor != tb_iterator_tail(iterator) && itor < pool->slot_count && pool->slot_list[itor]); // remove the slot if (itor + 1 < pool->slot_count) tb_memmov_(pool->slot_list + itor, pool->slot_list + itor + 1, (pool->slot_count - itor - 1) * sizeof(tb_fixed_pool_slot_t*)); // update the slot count pool->slot_count--; // exit slot tb_allocator_large_free(pool->large_allocator, slot); }
tb_bool_t vm86_parser_get_local_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value, tb_hash_map_ref_t proc_locals) { // check tb_assert(pp && e && value && proc_locals); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // get instruction name tb_char_t name[256] = {0}; if (!vm86_parser_get_variable_name(&p, e, name, sizeof(name))) break; // get value if (tb_hash_map_find(proc_locals, name) != tb_iterator_tail(proc_locals)) *value = (tb_uint32_t)tb_hash_map_get(proc_locals, name); else break; // trace tb_trace_d("local: %s: %u", name, *value); // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
static tb_size_t tb_vector_replace_test() { // init tb_vector_ref_t vector = tb_vector_init(TB_VECTOR_GROW_SIZE, tb_element_long()); tb_assert_and_check_return_val(vector, 0); tb_size_t n = 10000; tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n); __tb_volatile__ tb_size_t itor = tb_iterator_head(vector); __tb_volatile__ tb_size_t tail = tb_iterator_tail(vector); tb_hong_t t = tb_mclock(); for (; itor != tail; itor = tb_iterator_next(vector, itor)) tb_vector_replace(vector, itor, (tb_pointer_t)0xd); t = tb_mclock() - t; // time tb_trace_i("tb_vector_replace(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector)); // check tb_assert(tb_vector_size(vector) == n); tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd); tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd); // exit tb_vector_exit(vector); return n / ((tb_uint32_t)(t) + 1); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_remove_first_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value) { // check tb_assert_and_check_return(iterator && pred); // the iterator mode tb_size_t mode = tb_iterator_mode(iterator); tb_assert_and_check_return((mode & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return(!(mode & TB_ITERATOR_MODE_READONLY)); // done tb_size_t itor = tb_iterator_head(iterator); while (itor != tb_iterator_tail(iterator)) { // done predicate if (pred(iterator, tb_iterator_item(iterator, itor), value)) { // remove it tb_iterator_remove(iterator, itor); break; } // next itor = tb_iterator_next(iterator, itor); } }
tb_bool_t vm86_parser_get_offset_value(tb_char_t const** pp, tb_char_t const* e, tb_uint32_t* value, tb_hash_map_ref_t proc_labels, vm86_data_ref_t data) { // check tb_assert(pp && e && value && proc_labels); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // attempt to get segment name tb_char_t segment[16] = {0}; tb_bool_t has_segment = vm86_parser_get_segment_name(&p, e, segment, sizeof(segment)); // skip "short ..." if (p + 6 < e && !tb_strnicmp(p, "short ", 6)) p += 6; // skip the space while (p < e && tb_isspace(*p)) p++; // get instruction name tb_char_t name[256] = {0}; if (!vm86_parser_get_variable_name(&p, e, name, sizeof(name))) break; // is .data segment? if (has_segment && !tb_stricmp(segment, "ds")) *value = vm86_data_get(data, name, tb_null); // is .code segment? else if (has_segment && !tb_stricmp(segment, "cs")) *value = (tb_uint32_t)tb_hash_map_get(proc_labels, name); else { // get value if (tb_hash_map_find(proc_labels, name) != tb_iterator_tail(proc_labels)) *value = (tb_uint32_t)tb_hash_map_get(proc_labels, name); else if (vm86_data_is(data, name)) *value = vm86_data_get(data, name, tb_null); else break; } // check tb_assert(*value < TB_MAXU32); // trace tb_trace_d("offset: %s: %x", name, *value); // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }
static tb_ifaddrs_interface_ref_t tb_ifaddrs_interface_find(tb_iterator_ref_t iterator, tb_char_t const* name) { // check tb_assert_and_check_return_val(iterator && name, tb_null); // find it tb_size_t itor = tb_find_all_if(iterator, tb_ifaddrs_interface_pred, name); tb_check_return_val(itor != tb_iterator_tail(iterator), tb_null); // ok return (tb_ifaddrs_interface_ref_t)tb_iterator_item(iterator, itor); }
static tb_charset_ref_t tb_charset_find_by_name(tb_char_t const* name) { // init iterator tb_iterator_t iterator = tb_iterator_init_mem(g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t)); // find it by the binary search tb_size_t itor = tb_binary_find_all_if(&iterator, tb_charset_comp_by_name, name); // ok? if (itor != tb_iterator_tail(&iterator)) return (tb_charset_ref_t)tb_iterator_item(&iterator, itor); else return tb_null; }
static tb_charset_ref_t tb_charset_find_by_type(tb_size_t type) { // init iterator tb_iterator_t iterator = tb_iterator_init_mem(g_charsets, tb_arrayn(g_charsets), sizeof(tb_charset_t)); // find it by the binary search tb_size_t itor = tb_binary_find_all_if(&iterator, tb_charset_comp_by_type, (tb_cpointer_t)TB_CHARSET_TYPE(type)); // ok? if (itor != tb_iterator_tail(&iterator)) return (tb_charset_ref_t)tb_iterator_item(&iterator, itor); else return tb_null; }
static tb_void_t tb_find_str_test() { __tb_volatile__ tb_size_t i = 0; __tb_volatile__ tb_size_t n = 1000; // init data tb_char_t** data = (tb_char_t**)tb_nalloc0(n, sizeof(tb_char_t*)); tb_assert_and_check_return(data); // init iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_str(&array_iterator, data, n); // make tb_char_t s[256] = {0}; for (i = 0; i < n; i++) { tb_long_t r = tb_snprintf(s, 256, "%04lu", i); s[r] = '\0'; data[i] = tb_strdup(s); } // find tb_size_t itor = tb_iterator_tail(iterator); tb_hong_t time = tb_mclock(); for (i = 0; i < n; i++) itor = tb_find_all(iterator, (tb_pointer_t)data[800]); time = tb_mclock() - time; // item tb_char_t* item = itor != tb_iterator_tail(iterator)? (tb_char_t*)tb_iterator_item(iterator, itor) : 0; // time tb_trace_i("tb_find_str_all[%s ?= %s]: %lld ms", item, data[800], time); // free data for (i = 0; i < n; i++) tb_free(data[i]); tb_free(data); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t tb_rfind_if(tb_iterator_ref_t iterator, tb_size_t head, tb_size_t tail, tb_predicate_ref_t pred, tb_cpointer_t value) { // check tb_assert_and_check_return_val(pred && iterator && (tb_iterator_mode(iterator) & TB_ITERATOR_MODE_REVERSE), tb_iterator_tail(iterator)); // null? tb_check_return_val(head != tail, tb_iterator_tail(iterator)); // find tb_size_t itor = tail; tb_bool_t find = tb_false; do { // the previous item itor = tb_iterator_prev(iterator, itor); // comp if ((find = pred(iterator, tb_iterator_item(iterator, itor), value))) break; } while (itor != head); // ok? return find? itor : tb_iterator_tail(iterator); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ gb_color_t const gb_color_from_name(tb_char_t const* name) { // check tb_assert_and_check_return_val(name, GB_COLOR_DEFAULT); // init iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_iterator_make_for_mem(&array_iterator, g_named_colors, tb_arrayn(g_named_colors), sizeof(gb_named_color_t)); tb_assert(iterator); // find it by the binary search tb_size_t itor = tb_binary_find_all_if(iterator, gb_named_color_comp, name); // the color gb_named_color_t const* color = (itor != tb_iterator_tail(iterator))? (gb_named_color_t const*)tb_iterator_item(iterator, itor) : tb_null; // ok? return color? color->color : GB_COLOR_DEFAULT; }
tb_void_t tb_timer_task_kill(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("kill: when: %lld, period: %u, refn: %u", task_impl->when, task_impl->period, task_impl->refn); // enter tb_spinlock_enter(&impl->lock); // done do { // expired or removed? tb_check_break(task_impl->refn == 2); // find it tb_size_t itor = tb_find_all_if(impl->heap, tb_timer_comp_by_task, task_impl); tb_assert_and_check_break(itor != tb_iterator_tail(impl->heap)); // del this task_impl tb_heap_del(impl->heap, itor); // killed task_impl->killed = 1; // no repeat task_impl->repeat = 0; // modify when => now task_impl->when = tb_timer_now(impl); // re-add task_impl tb_heap_put(impl->heap, task_impl); } while (0); // leave tb_spinlock_leave(&impl->lock); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t gb_tessellator_triangulation_make(gb_tessellator_impl_t* impl) { // check tb_assert_abort(impl && impl->mesh); // the new face must be inserted to the head of faces tb_assert_abort(gb_mesh_face_order(impl->mesh) == GB_MESH_ORDER_INSERT_HEAD); // the iterator tb_iterator_ref_t iterator = gb_mesh_face_itor(impl->mesh); tb_assert_abort(iterator); // done tb_size_t itor = tb_iterator_head(iterator); tb_size_t tail = tb_iterator_tail(iterator); gb_mesh_face_ref_t face = tb_null; while (itor != tail) { // the face face = (gb_mesh_face_ref_t)tb_iterator_item(iterator, itor); tb_assert_abort(face); /* the next face * * @note we don't process the new faces at the head */ itor = tb_iterator_next(iterator, itor); // the face is inside? if (gb_tessellator_face_inside(face)) { // make triangulation for the face region gb_tessellator_triangulation_make_face(impl, face); } } #ifdef __gb_debug__ // check mesh gb_mesh_check(impl->mesh); #endif }
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_impl_t* impl, tb_pointer_t data) { // check tb_assert_and_check_return_val(impl && data, tb_null); // init the iterator tb_iterator_t iterator = tb_iterator_init_ptr((tb_pointer_t*)impl->slot_list, impl->slot_count); // find it tb_size_t itor = tb_binary_find_all_if(&iterator, tb_fixed_pool_slot_comp, data); tb_check_return_val(itor != tb_iterator_tail(&iterator), tb_null); // the slot tb_fixed_pool_slot_t* slot = impl->slot_list[itor]; tb_assert_and_check_return_val(slot, tb_null); // check tb_assert_abort(tb_fixed_pool_slot_exists(slot, data)); // ok? return slot; }
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; }
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_find(tb_fixed_pool_t* pool, tb_pointer_t data) { // check tb_assert_and_check_return_val(pool && data, tb_null); // make the iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_iterator_make_for_ptr(&array_iterator, (tb_pointer_t*)pool->slot_list, pool->slot_count); tb_assert(iterator); // find it tb_size_t itor = tb_binary_find_all_if(iterator, tb_fixed_pool_slot_comp, data); tb_check_return_val(itor != tb_iterator_tail(iterator), tb_null); // the slot tb_fixed_pool_slot_t* slot = pool->slot_list[itor]; tb_assert_and_check_return_val(slot, tb_null); // check tb_assert(tb_fixed_pool_slot_exists(slot, data)); // ok? return slot; }
static tb_pointer_t tb_thread_pool_worker_loop(tb_cpointer_t priv) { // the worker tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)priv; // trace tb_trace_d("worker[%lu]: init", worker? worker->id : -1); // done do { // check tb_assert_and_check_break(worker && !worker->jobs && !worker->stats); // the pool tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool; tb_assert_and_check_break(impl && impl->semaphore); // wait some time for leaving the lock tb_msleep((worker->id + 1)* 20); // init jobs worker->jobs = tb_vector_init(TB_THREAD_POOL_JOBS_WORKING_GROW, tb_element_ptr(tb_null, tb_null)); tb_assert_and_check_break(worker->jobs); // init stats worker->stats = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_ptr(tb_null, tb_null), tb_element_mem(sizeof(tb_thread_pool_job_stats_t), tb_null, tb_null)); tb_assert_and_check_break(worker->stats); // loop while (1) { // pull jobs if be idle if (!tb_vector_size(worker->jobs)) { // enter tb_spinlock_enter(&impl->lock); // init the pull time worker->pull = 0; // pull from the urgent jobs if (tb_list_entry_size(&impl->jobs_urgent)) { // trace tb_trace_d("worker[%lu]: try pulling from urgent: %lu", worker->id, tb_list_entry_size(&impl->jobs_urgent)); // pull it tb_remove_if_until(tb_list_entry_itor(&impl->jobs_urgent), tb_thread_pool_worker_walk_pull, worker); } // pull from the waiting jobs if (tb_list_entry_size(&impl->jobs_waiting)) { // trace tb_trace_d("worker[%lu]: try pulling from waiting: %lu", worker->id, tb_list_entry_size(&impl->jobs_waiting)); // pull it tb_remove_if_until(tb_list_entry_itor(&impl->jobs_waiting), tb_thread_pool_worker_walk_pull, worker); } // pull from the pending jobs and clean some finished and killed jobs if (tb_list_entry_size(&impl->jobs_pending)) { // trace tb_trace_d("worker[%lu]: try pulling from pending: %lu", worker->id, tb_list_entry_size(&impl->jobs_pending)); // no jobs? try to pull from the pending jobs if (!tb_vector_size(worker->jobs)) tb_remove_if(tb_list_entry_itor(&impl->jobs_pending), tb_thread_pool_worker_walk_pull_and_clean, worker); // clean some finished and killed jobs else tb_remove_if(tb_list_entry_itor(&impl->jobs_pending), tb_thread_pool_worker_walk_clean, worker); } // leave tb_spinlock_leave(&impl->lock); // idle? wait it if (!tb_vector_size(worker->jobs)) { // killed? tb_check_break(!tb_atomic_get(&worker->bstoped)); // trace tb_trace_d("worker[%lu]: wait: ..", worker->id); // wait some time tb_long_t wait = tb_semaphore_wait(impl->semaphore, -1); tb_assert_and_check_break(wait > 0); // trace tb_trace_d("worker[%lu]: wait: ok", worker->id); // continue it continue; } else { #ifdef TB_TRACE_DEBUG // update the jobs urgent size tb_size_t jobs_urgent_size = tb_list_entry_size(&impl->jobs_urgent); // update the jobs waiting size tb_size_t jobs_waiting_size = tb_list_entry_size(&impl->jobs_waiting); // update the jobs pending size tb_size_t jobs_pending_size = tb_list_entry_size(&impl->jobs_pending); // trace tb_trace_d("worker[%lu]: pull: jobs: %lu, time: %lu ms, waiting: %lu, pending: %lu, urgent: %lu", worker->id, tb_vector_size(worker->jobs), worker->pull, jobs_waiting_size, jobs_pending_size, jobs_urgent_size); #endif } } // done jobs tb_for_all (tb_thread_pool_job_t*, job, worker->jobs) { // check tb_assert_and_check_continue(job && job->task.done); // the job state tb_size_t state = tb_atomic_fetch_and_pset(&job->state, TB_STATE_WAITING, TB_STATE_WORKING); // the job is waiting? work it if (state == TB_STATE_WAITING) { // trace tb_trace_d("worker[%lu]: done: task[%p:%s]: ..", worker->id, job->task.done, job->task.name); // init the time tb_hong_t time = tb_cache_time_spak(); // done the job job->task.done((tb_thread_pool_worker_ref_t)worker, job->task.priv); // computate the time time = tb_cache_time_spak() - time; // exists? update time and count tb_size_t itor; tb_hash_map_item_ref_t item = tb_null; if ( ((itor = tb_hash_map_find(worker->stats, job->task.done)) != tb_iterator_tail(worker->stats)) && (item = (tb_hash_map_item_ref_t)tb_iterator_item(worker->stats, itor))) { // the stats tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)item->data; tb_assert_and_check_break(stats); // update the done count stats->done_count++; // update the total time stats->total_time += time; } // no item? add it if (!item) { // init stats tb_thread_pool_job_stats_t stats = {0}; stats.done_count = 1; stats.total_time = time; // add stats tb_hash_map_insert(worker->stats, job->task.done, &stats); } #ifdef TB_TRACE_DEBUG tb_size_t done_count = 0; tb_hize_t total_time = 0; tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)tb_hash_map_get(worker->stats, job->task.done); if (stats) { done_count = stats->done_count; total_time = stats->total_time; } // trace tb_trace_d("worker[%lu]: done: task[%p:%s]: time: %lld ms, average: %lld ms, count: %lu", worker->id, job->task.done, job->task.name, time, (total_time / (tb_hize_t)done_count), done_count); #endif // update the job state tb_atomic_set(&job->state, TB_STATE_FINISHED); } // the job is killing? work it else if (state == TB_STATE_KILLING) { // update the job state tb_atomic_set(&job->state, TB_STATE_KILLED); } } // clear jobs tb_vector_clear(worker->jobs); } } while (0); // exit worker if (worker) { // trace tb_trace_d("worker[%lu]: exit", worker->id); // stoped tb_atomic_set(&worker->bstoped, 1); // exit all private data tb_size_t i = 0; tb_size_t n = tb_arrayn(worker->priv); for (i = 0; i < n; i++) { // the private data tb_thread_pool_worker_priv_t* priv = &worker->priv[n - i - 1]; // exit it if (priv->exit) priv->exit((tb_thread_pool_worker_ref_t)worker, priv->priv); // clear it priv->exit = tb_null; priv->priv = tb_null; } // exit stats if (worker->stats) tb_hash_map_exit(worker->stats); worker->stats = tb_null; // exit jobs if (worker->jobs) tb_vector_exit(worker->jobs); worker->jobs = tb_null; } // exit tb_thread_return(tb_null); return tb_null; }
tb_void_t tb_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp) { tb_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp); }
static tb_void_t tb_test_heap_min_func() { // init heap tb_heap_ref_t heap = tb_heap_init(16, tb_element_uint32()); tb_assert_and_check_return(heap); // clear rand tb_random_clear(tb_null); // make heap tb_size_t i = 0; for (i = 0; i < 100; i++) { // the value tb_uint32_t val = tb_random_range(tb_null, 0, 50); // trace // tb_trace_i("heap_min: put: %u", val); // put it tb_heap_put(heap, tb_u2p(val)); } // clear rand tb_random_clear(tb_null); // remove some values for (i = 0; i < 100; i++) { // the value tb_uint32_t val = tb_random_range(tb_null, 0, 50); // remove it? if (!(i & 3)) { tb_size_t itor = tb_find_all(heap, tb_u2p(val)); if (itor != tb_iterator_tail(heap)) tb_heap_remove(heap, itor); } } // append heap for (i = 0; i < 30; i++) { // the value tb_uint32_t val = tb_random_range(tb_null, 0, 50); // put it tb_heap_put(heap, tb_u2p(val)); } // trace tb_trace_i(""); // dump heap while (tb_heap_size(heap)) { // put it tb_uint32_t val = (tb_uint32_t)(tb_size_t)tb_heap_top(heap); // trace tb_trace_i("heap_min: pop: %u", val); // pop it tb_heap_pop(heap); } // exit heap tb_heap_exit(heap); }
tb_size_t tb_rwalk_all(tb_iterator_ref_t iterator, tb_rwalk_func_t func, tb_cpointer_t priv) { return tb_rwalk(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), func, priv); }
tb_size_t tb_rfind_all_if(tb_iterator_ref_t iterator, tb_predicate_ref_t pred, tb_cpointer_t value) { return tb_rfind_if(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), pred, value); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t tb_remove_if(tb_iterator_ref_t iterator, tb_iterator_comp_t comp, tb_cpointer_t priv) { // check tb_assert_and_check_return(iterator && comp); // the iterator mode tb_size_t mode = tb_iterator_mode(iterator); tb_assert_and_check_return((mode & TB_ITERATOR_MODE_FORWARD)); tb_assert_and_check_return(!(mode & TB_ITERATOR_MODE_READONLY)); // done tb_long_t ok = 1; tb_size_t size = 0; tb_bool_t stop = tb_false; tb_bool_t need = tb_false; tb_size_t prev = tb_iterator_tail(iterator); tb_size_t itor = tb_iterator_head(iterator); tb_size_t base = tb_iterator_tail(iterator); tb_bool_t bmutable = (mode & TB_ITERATOR_MODE_MUTABLE)? tb_true : tb_false; while (itor != tb_iterator_tail(iterator)) { // save next tb_size_t next = tb_iterator_next(iterator, itor); // done func if ((ok = comp(iterator, tb_iterator_item(iterator, itor), priv)) < 0) stop = tb_true; // remove it? if (!ok) { // is the first removed item? if (!need) { // save the removed range base base = prev; // need remove items need = tb_true; } // update size size++; } // the removed range have been passed or stop or end? if (ok || next == tb_iterator_tail(iterator)) { // need remove items? if (need) { // check tb_assert_abort(size); // the previous tail tb_size_t prev_tail = tb_iterator_tail(iterator); // remove items tb_iterator_remove_range(iterator, base, !ok? next : itor, size); // reset state need = tb_false; size = 0; // is the mutable iterator? if (bmutable) { // update itor prev = base; // the body items are removed? if (base != prev_tail) { // the next itor itor = tb_iterator_next(iterator, base); // the last item be not removed? skip the last walked item if (ok) { prev = itor; itor = tb_iterator_next(iterator, itor); } } // the head items are removed? else itor = tb_iterator_head(iterator); // stop? tb_check_break(!stop); // continue? continue ; } } // stop? tb_check_break(!stop); } // next prev = itor; itor = next; } }
tb_void_t tb_fixed_pool_clear(tb_fixed_pool_ref_t pool) { // check tb_fixed_pool_impl_t* impl = (tb_fixed_pool_impl_t*)pool; tb_assert_and_check_return(impl); // exit items if (impl->func_exit) tb_fixed_pool_walk(pool, tb_fixed_pool_item_exit, (tb_pointer_t)impl); // exit the current slot first if (impl->current_slot) tb_fixed_pool_slot_exit(impl, impl->current_slot); impl->current_slot = tb_null; // exit the partial slots tb_iterator_ref_t partial_iterator = tb_list_entry_itor(&impl->partial_slots); if (partial_iterator) { // walk it tb_size_t itor = tb_iterator_head(partial_iterator); while (itor != tb_iterator_tail(partial_iterator)) { // the slot tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)tb_iterator_item(partial_iterator, itor); tb_assert_and_check_break(slot); // save next tb_size_t next = tb_iterator_next(partial_iterator, itor); // exit data tb_fixed_pool_slot_exit(impl, slot); // next itor = next; } } // exit the full slots tb_iterator_ref_t full_iterator = tb_list_entry_itor(&impl->full_slots); if (full_iterator) { // walk it tb_size_t itor = tb_iterator_head(full_iterator); while (itor != tb_iterator_tail(full_iterator)) { // the slot tb_fixed_pool_slot_t* slot = (tb_fixed_pool_slot_t*)tb_iterator_item(full_iterator, itor); tb_assert_and_check_break(slot); // save next tb_size_t next = tb_iterator_next(full_iterator, itor); // exit data tb_fixed_pool_slot_exit(impl, slot); // next itor = next; } } // clear item count impl->item_count = 0; // clear current slot impl->current_slot = tb_null; // clear partial slots tb_list_entry_clear(&impl->partial_slots); // clear full slots tb_list_entry_clear(&impl->full_slots); }
tb_size_t tb_list_insert_tail(tb_list_ref_t self, tb_cpointer_t data) { return tb_list_insert_prev(self, tb_iterator_tail(self), data); }
static tb_long_t tb_aiop_rtor_select_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout) { // check tb_aiop_rtor_select_impl_t* impl = (tb_aiop_rtor_select_impl_t*)rtor; tb_assert_and_check_return_val(impl && rtor->aiop && list && maxn, -1); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, tb_false); // init time struct timeval t = {0}; if (timeout > 0) { #ifdef TB_CONFIG_OS_WINDOWS t.tv_sec = (LONG)(timeout / 1000); #else t.tv_sec = (timeout / 1000); #endif t.tv_usec = (timeout % 1000) * 1000; } // loop tb_long_t wait = 0; tb_bool_t stop = tb_false; tb_hong_t time = tb_mclock(); while (!wait && !stop && (timeout < 0 || tb_mclock() < time + timeout)) { // enter tb_spinlock_enter(&impl->lock.pfds); // init fdo tb_size_t sfdm = impl->sfdm; tb_memcpy(&impl->rfdo, &impl->rfdi, sizeof(fd_set)); tb_memcpy(&impl->wfdo, &impl->wfdi, sizeof(fd_set)); // leave tb_spinlock_leave(&impl->lock.pfds); // wait #ifdef TB_CONFIG_OS_WINDOWS tb_long_t sfdn = tb_ws2_32()->select((tb_int_t)sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null); #else tb_long_t sfdn = select(sfdm + 1, &impl->rfdo, &impl->wfdo, tb_null, timeout >= 0? &t : tb_null); #endif tb_assert_and_check_return_val(sfdn >= 0, -1); // timeout? tb_check_return_val(sfdn, 0); // enter tb_spinlock_enter(&impl->lock.hash); // sync tb_size_t itor = tb_iterator_head(impl->hash); tb_size_t tail = tb_iterator_tail(impl->hash); for (; itor != tail && wait >= 0 && (tb_size_t)wait < maxn; itor = tb_iterator_next(impl->hash, itor)) { tb_hash_map_item_ref_t item = (tb_hash_map_item_ref_t)tb_iterator_item(impl->hash, itor); if (item) { // the sock tb_socket_ref_t sock = (tb_socket_ref_t)item->name; tb_assert_and_check_return_val(sock, -1); // spak? if (sock == aiop->spak[1] && FD_ISSET(((tb_long_t)aiop->spak[1] - 1), &impl->rfdo)) { // read spak tb_char_t spak = '\0'; if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) wait = -1; // killed? if (spak == 'k') wait = -1; tb_check_break(wait >= 0); // stop to wait stop = tb_true; // continue it continue ; } // filter spak tb_check_continue(sock != aiop->spak[1]); // the fd tb_long_t fd = (tb_long_t)item->name - 1; // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)item->data; tb_assert_and_check_return_val(aioo && aioo->sock == sock, -1); // init aioe tb_aioe_t aioe = {0}; aioe.priv = aioo->priv; aioe.aioo = (tb_aioo_ref_t)aioo; if (FD_ISSET(fd, &impl->rfdo)) { aioe.code |= TB_AIOE_CODE_RECV; if (aioo->code & TB_AIOE_CODE_ACPT) aioe.code |= TB_AIOE_CODE_ACPT; } if (FD_ISSET(fd, &impl->wfdo)) { aioe.code |= TB_AIOE_CODE_SEND; if (aioo->code & TB_AIOE_CODE_CONN) aioe.code |= TB_AIOE_CODE_CONN; } // ok? if (aioe.code) { // save aioe list[wait++] = aioe; // oneshot? clear it if (aioo->code & TB_AIOE_CODE_ONESHOT) { // clear aioo aioo->code = TB_AIOE_CODE_NONE; aioo->priv = tb_null; // clear events tb_spinlock_enter(&impl->lock.pfds); FD_CLR(fd, &impl->rfdi); FD_CLR(fd, &impl->wfdi); tb_spinlock_leave(&impl->lock.pfds); } } } } // leave tb_spinlock_leave(&impl->lock.hash); } // ok return wait; }
tb_void_t tb_list_moveto_tail(tb_list_ref_t self, tb_size_t move) { tb_list_moveto_prev(self, tb_iterator_tail(self), move); }
tb_bool_t vm86_parser_get_register(tb_char_t const** pp, tb_char_t const* e, tb_uint16_t* r) { // check tb_assert(pp && e && r); // done tb_bool_t ok = tb_false; tb_char_t const* p = *pp; do { // save base tb_char_t const* b = p; // get instruction name tb_char_t name[64] = {0}; while (p < e && tb_isalpha(*p)) p++; tb_check_break(p <= e && p - b < sizeof(name)); tb_memcpy(name, b, p - b); // skip the space while (p < e && tb_isspace(*p)) p++; // the register entry type typedef struct __vm86_register_entry_t { // the register name tb_char_t const* name; // the register index tb_uint8_t index; }vm86_register_entry_t, *vm86_register_entry_ref_t; // the registers static vm86_register_entry_t s_registers[] = { { "ah", VM86_REGISTER_EAX | VM86_REGISTER_AH } , { "al", VM86_REGISTER_EAX | VM86_REGISTER_AL } , { "ax", VM86_REGISTER_EAX | VM86_REGISTER_AX } , { "bh", VM86_REGISTER_EBX | VM86_REGISTER_BH } , { "bl", VM86_REGISTER_EBX | VM86_REGISTER_BL } , { "bx", VM86_REGISTER_EBX | VM86_REGISTER_BX } , { "ch", VM86_REGISTER_ECX | VM86_REGISTER_CH } , { "cl", VM86_REGISTER_ECX | VM86_REGISTER_CL } , { "cx", VM86_REGISTER_ECX | VM86_REGISTER_CX } , { "dh", VM86_REGISTER_EDX | VM86_REGISTER_DH } , { "dl", VM86_REGISTER_EDX | VM86_REGISTER_DL } , { "dx", VM86_REGISTER_EDX | VM86_REGISTER_DX } , { "eax", VM86_REGISTER_EAX } , { "ebp", VM86_REGISTER_EBP } , { "ebx", VM86_REGISTER_EBX } , { "ecx", VM86_REGISTER_ECX } , { "edi", VM86_REGISTER_EDI } , { "edx", VM86_REGISTER_EDX } , { "esi", VM86_REGISTER_ESI } , { "esp", VM86_REGISTER_ESP } }; // init iterator tb_array_iterator_t array_iterator; tb_iterator_ref_t iterator = tb_array_iterator_init_mem(&array_iterator, s_registers, tb_arrayn(s_registers), sizeof(vm86_register_entry_t)); // find register by the binary search tb_size_t itor = tb_binary_find_all_if(iterator, vm86_parser_comp_register, name); tb_check_break(itor != tb_iterator_tail(iterator)); // get the register vm86_register_entry_ref_t entry = (vm86_register_entry_ref_t)tb_iterator_item(iterator, itor); tb_assert_and_check_break(entry && (entry->index & VM86_REGISTER_MASK) < VM86_REGISTER_MAXN); // save register *r = entry->index; // trace tb_trace_d("register: %s: %x", name, entry->index); // ok ok = tb_true; } while (0); // update the code pointer if ok if (ok) *pp = p; // ok? return ok; }