tb_void_t tb_fixed_pool_exit(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return(pool); // clear it tb_fixed_pool_clear(self); // exit the current slot if (pool->current_slot) tb_fixed_pool_slot_exit(pool, pool->current_slot); pool->current_slot = tb_null; // exit the slot list if (pool->slot_list) tb_allocator_large_free(pool->large_allocator, pool->slot_list); pool->slot_list = tb_null; pool->slot_count = 0; pool->slot_space = 0; // exit it tb_allocator_large_free(pool->large_allocator, pool); }
tb_bool_t tb_fixed_pool_free_(tb_fixed_pool_ref_t pool, tb_pointer_t data __tb_debug_decl__) { // check tb_fixed_pool_impl_t* impl = (tb_fixed_pool_impl_t*)pool; tb_assert_and_check_return_val(impl, tb_false); // done tb_bool_t ok = tb_false; do { // check tb_assertf_and_check_break(impl->item_count, "double free data: %p", data); // find the slot tb_fixed_pool_slot_t* slot = tb_fixed_pool_slot_find(impl, data); tb_assertf_and_check_break(slot, "the data: %p not belong to pool: %p", data, pool); tb_assert_and_check_break(slot->pool); // the slot is full? tb_bool_t full = tb_static_fixed_pool_full(slot->pool); // done exit if (impl->func_exit) impl->func_exit(data, impl->func_priv); // free it if (!tb_static_fixed_pool_free(slot->pool, data __tb_debug_args__)) break; // not the current slot? if (slot != impl->current_slot) { // is full? move the slot to the partial slots if (full) { tb_list_entry_remove(&impl->full_slots, &slot->entry); tb_list_entry_insert_tail(&impl->partial_slots, &slot->entry); } // is null? exit the slot else if (tb_static_fixed_pool_null(slot->pool)) { tb_list_entry_remove(&impl->partial_slots, &slot->entry); tb_fixed_pool_slot_exit(impl, slot); } } // update the item count impl->item_count--; // ok ok = tb_true; } while (0); // failed? dump it #ifdef __tb_debug__ if (!ok) { // trace tb_trace_e("free(%p) failed! at %s(): %lu, %s", data, func_, line_, file_); // dump data tb_pool_data_dump((tb_byte_t const*)data, tb_true, "[fixed_pool]: [error]: "); // abort tb_abort(); } #endif // ok? return ok; }
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); }
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_init(tb_fixed_pool_impl_t* impl) { // check tb_assert_and_check_return_val(impl && impl->large_pool && impl->slot_size && impl->item_size, tb_null); // done tb_bool_t ok = tb_false; tb_fixed_pool_slot_t* slot = tb_null; do { #ifdef __tb_debug__ // init patch for checking underflow tb_size_t patch = 1; #else tb_size_t patch = 0; #endif // the item space tb_size_t item_space = sizeof(tb_pool_data_head_t) + impl->item_size + patch; // the need space tb_size_t need_space = sizeof(tb_fixed_pool_slot_t) + impl->slot_size * item_space; // make slot tb_size_t real_space = 0; slot = (tb_fixed_pool_slot_t*)tb_large_pool_malloc(impl->large_pool, need_space, &real_space); tb_assert_and_check_break(slot); tb_assert_and_check_break(real_space > sizeof(tb_fixed_pool_slot_t) + item_space); #ifdef __tb_debug__ // remove the debug space size tb_large_pool_diff(impl->large_pool, -(tb_long_t)(impl->slot_size * (TB_POOL_DATA_HEAD_DIFF_SIZE + patch))); #endif // init slot slot->size = real_space; slot->pool = tb_static_fixed_pool_init((tb_byte_t*)&slot[1], real_space - sizeof(tb_fixed_pool_slot_t), impl->item_size, impl->for_small_pool); tb_assert_and_check_break(slot->pool); // no list? if (!impl->slot_list) { // init the slot list tb_size_t size = 0; impl->slot_list = (tb_fixed_pool_slot_t**)tb_large_pool_nalloc(impl->large_pool, 64, sizeof(tb_fixed_pool_slot_t*), &size); tb_assert_and_check_break(impl->slot_list && size); // init the slot count impl->slot_count = 0; // init the slot space impl->slot_space = size / sizeof(tb_fixed_pool_slot_t*); tb_assert_and_check_break(impl->slot_space); } // no enough space? else if (impl->slot_count == impl->slot_space) { // grow the slot list tb_size_t size = 0; impl->slot_list = (tb_fixed_pool_slot_t**)tb_large_pool_ralloc(impl->large_pool, impl->slot_list, (impl->slot_space << 1) * sizeof(tb_fixed_pool_slot_t*), &size); tb_assert_and_check_break(impl->slot_list && size); // update the slot space impl->slot_space = size / sizeof(tb_fixed_pool_slot_t*); tb_assert_and_check_break(impl->slot_space); } // check tb_assert_and_check_break(impl->slot_count < impl->slot_space); // insert the slot to the slot list in the increasing order tb_size_t i = 0; tb_size_t n = impl->slot_count; for (i = 0; i < n; i++) if (slot <= impl->slot_list[i]) break; if (i < n) tb_memmov_(impl->slot_list + i + 1, impl->slot_list + i, (n - i) * sizeof(tb_fixed_pool_slot_t*)); impl->slot_list[i] = slot; // update the slot count impl->slot_count++; // trace tb_trace_d("slot[%lu]: init: size: %lu => %lu, item: %lu => %lu", impl->item_size, need_space, real_space, impl->slot_size, tb_static_fixed_pool_maxn(slot->pool)); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (slot) tb_fixed_pool_slot_exit(impl, slot); slot = tb_null; } // ok? return slot; }
tb_void_t tb_fixed_pool_clear(tb_fixed_pool_ref_t self) { // check tb_fixed_pool_t* pool = (tb_fixed_pool_t*)self; tb_assert_and_check_return(pool); // exit items if (pool->func_exit) tb_fixed_pool_walk(self, tb_fixed_pool_item_exit, (tb_pointer_t)pool); // exit the partial slots tb_iterator_ref_t partial_iterator = tb_list_entry_itor(&pool->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); // check tb_assert(slot != pool->current_slot); // save next tb_size_t next = tb_iterator_next(partial_iterator, itor); // exit slot tb_fixed_pool_slot_exit(pool, slot); // next itor = next; } } // exit the full slots tb_iterator_ref_t full_iterator = tb_list_entry_itor(&pool->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); // check tb_assert(slot != pool->current_slot); // save next tb_size_t next = tb_iterator_next(full_iterator, itor); // exit slot tb_fixed_pool_slot_exit(pool, slot); // next itor = next; } } // clear current slot if (pool->current_slot && pool->current_slot->pool) tb_static_fixed_pool_clear(pool->current_slot->pool); // clear item count pool->item_count = 0; // clear partial slots tb_list_entry_clear(&pool->partial_slots); // clear full slots tb_list_entry_clear(&pool->full_slots); }
static tb_fixed_pool_slot_t* tb_fixed_pool_slot_init(tb_fixed_pool_t* pool) { // check tb_assert_and_check_return_val(pool && pool->large_allocator && pool->slot_size && pool->item_size, tb_null); // done tb_bool_t ok = tb_false; tb_fixed_pool_slot_t* slot = tb_null; do { #ifdef __tb_debug__ // init patch for checking underflow tb_size_t patch = 1; #else tb_size_t patch = 0; #endif // the item space tb_size_t item_space = sizeof(tb_pool_data_head_t) + pool->item_size + patch; // the need space tb_size_t need_space = sizeof(tb_fixed_pool_slot_t) + pool->slot_size * item_space; // make slot tb_size_t real_space = 0; slot = (tb_fixed_pool_slot_t*)tb_allocator_large_malloc(pool->large_allocator, need_space, &real_space); tb_assert_and_check_break(slot); tb_assert_and_check_break(real_space > sizeof(tb_fixed_pool_slot_t) + item_space); // init slot slot->size = real_space; slot->pool = tb_static_fixed_pool_init((tb_byte_t*)&slot[1], real_space - sizeof(tb_fixed_pool_slot_t), pool->item_size, pool->for_small); tb_assert_and_check_break(slot->pool); // no list? if (!pool->slot_list) { // init the slot list tb_size_t size = 0; pool->slot_list = (tb_fixed_pool_slot_t**)tb_allocator_large_nalloc(pool->large_allocator, 64, sizeof(tb_fixed_pool_slot_t*), &size); tb_assert_and_check_break(pool->slot_list && size); // init the slot count pool->slot_count = 0; // init the slot space pool->slot_space = size / sizeof(tb_fixed_pool_slot_t*); tb_assert_and_check_break(pool->slot_space); } // no enough space? else if (pool->slot_count == pool->slot_space) { // grow the slot list tb_size_t size = 0; pool->slot_list = (tb_fixed_pool_slot_t**)tb_allocator_large_ralloc(pool->large_allocator, pool->slot_list, (pool->slot_space << 1) * sizeof(tb_fixed_pool_slot_t*), &size); tb_assert_and_check_break(pool->slot_list && size); // update the slot space pool->slot_space = size / sizeof(tb_fixed_pool_slot_t*); tb_assert_and_check_break(pool->slot_space); } // check tb_assert_and_check_break(pool->slot_count < pool->slot_space); // insert the slot to the slot list in the increasing order (TODO binary search) tb_size_t i = 0; tb_size_t n = pool->slot_count; for (i = 0; i < n; i++) if (slot <= pool->slot_list[i]) break; if (i < n) tb_memmov_(pool->slot_list + i + 1, pool->slot_list + i, (n - i) * sizeof(tb_fixed_pool_slot_t*)); pool->slot_list[i] = slot; // update the slot count pool->slot_count++; // trace tb_trace_d("slot[%lu]: init: size: %lu => %lu, item: %lu => %lu", pool->item_size, need_space, real_space, pool->slot_size, tb_static_fixed_pool_maxn(slot->pool)); // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (slot) tb_fixed_pool_slot_exit(pool, slot); slot = tb_null; } // ok? return slot; }