tb_void_t tb_fixed_pool_dump(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); // dump the current slot first if (impl->current_slot && impl->current_slot->pool) tb_static_fixed_pool_dump(impl->current_slot->pool); // dump the partial slots tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&impl->partial_slots), partial_slot && partial_slot->pool) { // check tb_assert_abort(!tb_static_fixed_pool_full(partial_slot->pool)); // dump tb_static_fixed_pool_dump(partial_slot->pool); } // dump the full slots tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&impl->full_slots), full_slot && full_slot->pool) { // check tb_assert_abort(tb_static_fixed_pool_full(full_slot->pool)); // dump tb_static_fixed_pool_dump(full_slot->pool); } }
tb_void_t tb_fixed_pool_walk(tb_fixed_pool_ref_t pool, tb_fixed_pool_item_walk_func_t func, tb_cpointer_t priv) { // check tb_fixed_pool_impl_t* impl = (tb_fixed_pool_impl_t*)pool; tb_assert_and_check_return(impl && func); // walk the current slot first if (impl->current_slot && impl->current_slot->pool) tb_static_fixed_pool_walk(impl->current_slot->pool, func, priv); // walk the partial slots tb_for_all_if(tb_fixed_pool_slot_t*, partial_slot, tb_list_entry_itor(&impl->partial_slots), partial_slot && partial_slot->pool) { // check tb_assert_abort(!tb_static_fixed_pool_full(partial_slot->pool)); // walk tb_static_fixed_pool_walk(partial_slot->pool, func, priv); } // walk the full slots tb_for_all_if(tb_fixed_pool_slot_t*, full_slot, tb_list_entry_itor(&impl->full_slots), full_slot && full_slot->pool) { // check tb_assert_abort(tb_static_fixed_pool_full(full_slot->pool)); // walk tb_static_fixed_pool_walk(full_slot->pool, func, priv); } }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementions */ gb_pixmap_ref_t gb_pixmap(tb_size_t pixfmt, tb_byte_t alpha) { // big endian? tb_size_t bendian = GB_PIXFMT_BE(pixfmt); // the pixfmt pixfmt = GB_PIXFMT(pixfmt); tb_assert_abort(pixfmt); // opaque? if (alpha > GB_ALPHA_MAXN) { // check tb_assert_abort(pixfmt && (pixfmt - 1) < tb_arrayn(g_pixmaps_lo)); // ok return bendian? g_pixmaps_bo[pixfmt - 1] : g_pixmaps_lo[pixfmt - 1]; } // alpha? else if (alpha >= GB_ALPHA_MINN) { // check tb_assert_abort(pixfmt && (pixfmt - 1) < tb_arrayn(g_pixmaps_la)); // ok return bendian? g_pixmaps_ba[pixfmt - 1] : g_pixmaps_la[pixfmt - 1]; } // transparent return tb_null; }
static tb_void_t tb_single_list_entry_itor_copy(tb_iterator_ref_t iterator, tb_size_t itor, tb_cpointer_t item) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert_abort(list && list->copy); tb_assert_abort(list->eoff < itor && item); // copy it list->copy((tb_pointer_t)(itor - list->eoff), (tb_pointer_t)item); }
static tb_void_t tb_element_str_repl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data) { // check tb_assert_and_check_return(element && element->dupl && buff); #if 0 // free it if (element->free) element->free(element, buff); // dupl it element->dupl(element, buff, data); #else // replace it tb_pointer_t cstr = *((tb_pointer_t*)buff); if (cstr && data) { // attempt to replace it tb_char_t* p = (tb_char_t*)cstr; tb_char_t const* q = (tb_char_t const*)data; while (*p && *q) *p++ = *q++; // not enough space? if (!*p && *q) { // the left size tb_size_t left = tb_strlen(q); tb_assert_abort(left); // the copy size tb_size_t copy = p - (tb_char_t*)cstr; // grow size cstr = tb_ralloc(cstr, copy + left + 1); tb_assert_abort(cstr); // copy the left data tb_strlcpy((tb_char_t*)cstr + copy, q, left + 1); // update the cstr *((tb_pointer_t*)buff) = cstr; } // end else *p = '\0'; } // duplicate it else if (data) element->dupl(element, buff, data); // free it else if (element->free) element->free(element, buff); // clear it else *((tb_char_t const**)buff) = tb_null; #endif }
tb_pointer_t tb_pool_align_malloc_(tb_pool_ref_t pool, tb_size_t size, tb_size_t align __tb_debug_decl__) { // check tb_assertf_abort(!(align & 3), "invalid alignment size: %lu", align); tb_check_return_val(!(align & 3), tb_null); // malloc it tb_byte_t* data = (tb_byte_t*)tb_pool_malloc_(pool, size + align __tb_debug_args__); tb_check_return_val(data, tb_null); // the different bytes tb_byte_t diff = (tb_byte_t)((~(tb_long_t)data) & (align - 1)) + 1; // adjust the address data += diff; // check tb_assert_abort(!((tb_size_t)data & (align - 1))); // save the different bytes data[-1] = diff; // ok? return (tb_pointer_t)data; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t gb_bitmap_biltter_shader_init(gb_bitmap_biltter_ref_t biltter, gb_bitmap_ref_t bitmap, gb_paint_ref_t paint) { // check tb_assert_abort(biltter && bitmap && paint); // init bitmap biltter->bitmap = bitmap; // init pixmap biltter->pixmap = gb_pixmap(gb_bitmap_pixfmt(bitmap), gb_paint_alpha(paint)); tb_check_return_val(biltter->pixmap, tb_false); // init btp and row_bytes biltter->btp = biltter->pixmap->btp; biltter->row_bytes = gb_bitmap_row_bytes(biltter->bitmap); // init shader // TODO // init operations // TODO // trace tb_trace_noimpl(); // ok return tb_false; }
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); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_size_t gb_float_unit_divide(gb_float_t numer, gb_float_t denom, gb_float_t* result) { // check tb_assert_abort(result); // negate it if (numer < 0) { numer = -numer; denom = -denom; } // must be valid numerator and denominator if (0 == denom || 0 == numer || numer >= denom) return 0; // the result: numer / denom gb_float_t r = gb_div(numer, denom); // must be finite value tb_assert_and_check_return_val(gb_isfinite(r), 0); // must be in range: [0, 1) tb_assert_and_check_return_val(r >= 0 && r < GB_ONE, 0); // too smaller? not save result tb_check_return_val(r != 0, 0); // save result *result = r; // ok return 1; }
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); }
tb_void_t gb_bitmap_render_stroke_polygon(gb_bitmap_device_ref_t device, gb_polygon_ref_t polygon) { // check tb_assert_abort(device && polygon && polygon->points && polygon->counts); // done tb_uint16_t index = 0; gb_point_t points_line[2]; gb_point_ref_t points = polygon->points; tb_uint16_t* counts = polygon->counts; tb_uint16_t count = *counts++; while (index < count) { // the point points_line[1] = *points++; // stroke line if (index) gb_bitmap_render_stroke_lines(device, points_line, 2); // save the previous point points_line[0] = points_line[1]; // next point index++; // next polygon if (index == count) { // next count = *counts++; index = 0; } } }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t gb_bitmap_render_fill_polygon(gb_bitmap_device_ref_t device, gb_polygon_ref_t polygon, gb_rect_ref_t bounds) { // check tb_assert_abort(device && device->base.paint); // done raster gb_polygon_raster_done(device->raster, polygon, bounds, gb_paint_fill_rule(device->base.paint), gb_bitmap_render_fill_raster, &device->biltter); }
static tb_bool_t tb_ifaddrs_interface_pred(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t name) { // check tb_assert_abort(item); // is equal? return !tb_stricmp(((tb_ifaddrs_interface_ref_t)item)->name, (tb_char_t const*)name); }
tb_bool_t tb_predicate_beq(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value) { // check tb_assert_abort(iterator); // item >= value? return tb_iterator_comp(iterator, item, value) >= 0; }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_void_t gb_bitmap_render_fill_raster(tb_long_t lx, tb_long_t rx, tb_long_t yb, tb_long_t ye, tb_cpointer_t priv) { // check tb_assert_abort(priv && rx >= lx && ye > yb); // done biltter gb_bitmap_biltter_done_r((gb_bitmap_biltter_ref_t)priv, lx, yb, rx - lx, ye - yb); }
static tb_size_t tb_single_list_entry_itor_next(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_assert_abort(itor); // next return (tb_size_t)((tb_single_list_entry_ref_t)itor)->next; }
tb_bool_t gb_point_near_eq(gb_point_ref_t point, gb_point_ref_t other) { // check tb_assert_abort(point && other); // equal? return (gb_near_eq(point->x, other->x)) && (gb_near_eq(point->y, other->y)); }
/* ////////////////////////////////////////////////////////////////////////////////////// * 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; }
/* ////////////////////////////////////////////////////////////////////////////////////// * iterator implementation */ static tb_size_t tb_single_list_entry_itor_size(tb_iterator_ref_t iterator) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert_abort(list); // the size return list->size; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t gb_point_make(gb_point_ref_t point, gb_float_t x, gb_float_t y) { // check tb_assert_abort(point); // make it point->x = x; point->y = y; }
static tb_pointer_t tb_single_list_entry_itor_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert_abort(list && list->eoff < itor); // data return (tb_pointer_t)(itor - list->eoff); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_double_t tb_sin(tb_double_t x) { #ifdef TB_CONFIG_LIBM_HAVE_SIN return sin(x); #else tb_assert_abort(0); return 0; #endif }
/* ////////////////////////////////////////////////////////////////////////////////////// * interfaces */ tb_dns_looker_ref_t tb_dns_looker_init(tb_char_t const* name) { // check tb_assert_and_check_return_val(name, tb_null); // must be not address tb_assert_abort(!tb_ipaddr_ip_cstr_set(tb_null, name, TB_IPADDR_FAMILY_NONE)); // done tb_bool_t ok = tb_false; tb_dns_looker_impl_t* impl = tb_null; do { // make impl impl = tb_malloc0_type(tb_dns_looker_impl_t); tb_assert_and_check_return_val(impl, tb_null); // dump server // tb_dns_server_dump(); // get the dns server list impl->maxn = tb_dns_server_get(impl->list); tb_check_break(impl->maxn && impl->maxn <= tb_arrayn(impl->list)); // init name if (!tb_static_string_init(&impl->name, (tb_char_t*)impl->data, TB_DNS_NAME_MAXN)) break; tb_static_string_cstrcpy(&impl->name, name); // init rpkt if (!tb_static_buffer_init(&impl->rpkt, impl->data + TB_DNS_NAME_MAXN, TB_DNS_RPKT_MAXN)) break; // init family impl->family = TB_IPADDR_FAMILY_IPV4; // init sock impl->sock = tb_socket_init(TB_SOCKET_TYPE_UDP, impl->family); tb_assert_and_check_break(impl->sock); // init itor impl->itor = 1; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (impl) tb_dns_looker_exit((tb_dns_looker_ref_t)impl); impl = tb_null; } // ok? return (tb_dns_looker_ref_t)impl; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_double_t tb_sqrt(tb_double_t x) { #ifdef TB_CONFIG_LIBM_HAVE_SQRT return sqrt(x); #else tb_assert_abort(0); return 0; #endif }
static tb_size_t tb_single_list_entry_itor_last(tb_iterator_ref_t iterator) { // check tb_single_list_entry_head_ref_t list = tb_container_of(tb_single_list_entry_head_t, itor, iterator); tb_assert_abort(list); // last return (tb_size_t)list->last; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_float_t tb_cosf(tb_float_t x) { #ifdef TB_CONFIG_LIBM_HAVE_COSF return cosf(x); #else tb_assert_abort(0); return 0; #endif }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t gb_circle_make(gb_circle_ref_t circle, gb_float_t x0, gb_float_t y0, gb_float_t r) { // check tb_assert_abort(circle); // make it circle->c.x = x0; circle->c.y = y0; circle->r = r; }
tb_size_t gb_mesh_face_list_size(gb_mesh_face_list_ref_t list) { // check gb_mesh_face_list_impl_t* impl = (gb_mesh_face_list_impl_t*)list; tb_assert_and_check_return_val(impl && impl->pool, 0); tb_assert_abort(tb_list_entry_size(&impl->head) == tb_fixed_pool_size(impl->pool)); // the size return tb_list_entry_size(&impl->head); }
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; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_void_t gb_bitmap_render_stroke_points(gb_bitmap_device_ref_t device, gb_point_ref_t points, tb_size_t count) { // check tb_assert_abort(device && points && count); // done tb_size_t i; for (i = 0; i < count; i++) gb_bitmap_biltter_done_p(&device->biltter, gb_float_to_long(points[i].x), gb_float_to_long(points[i].y)); }