tb_bool_t tb_lo_scheduler_io_cancel(tb_lo_scheduler_io_ref_t scheduler_io, tb_socket_ref_t sock) { // check tb_assert(scheduler_io && sock && scheduler_io->poller && scheduler_io->scheduler); // get the current coroutine tb_lo_coroutine_t* coroutine = tb_lo_scheduler_running(scheduler_io->scheduler); tb_check_return_val(coroutine, tb_false); // trace tb_trace_d("coroutine(%p): cancel socket(%p) ..", coroutine, sock); // remove the this socket from poller if (coroutine->rs.wait.sock == sock) { // remove the previous socket first if exists if (!tb_poller_remove(scheduler_io->poller, sock)) { // trace tb_trace_e("failed to remove sock(%p) to poller on coroutine(%p)!", sock, coroutine); // failed coroutine->rs.wait.events_result = -1; return tb_false; } // clear waited socket coroutine->rs.wait.sock = tb_null; // remove ok coroutine->rs.wait.events_result = 0; return tb_true; } // no this socket return tb_false; }
tb_double_t tb_oc_number_double(tb_object_ref_t object) { // check tb_oc_number_t* number = tb_oc_number_cast(object); tb_assert_and_check_return_val(number, 0); // double switch (number->type) { case TB_OC_NUMBER_TYPE_DOUBLE: return number->v.d; case TB_OC_NUMBER_TYPE_FLOAT: return (tb_double_t)number->v.f; case TB_OC_NUMBER_TYPE_UINT8: return (tb_double_t)number->v.u8; case TB_OC_NUMBER_TYPE_SINT8: return (tb_double_t)number->v.s8; case TB_OC_NUMBER_TYPE_UINT16: return (tb_double_t)number->v.u16; case TB_OC_NUMBER_TYPE_SINT16: return (tb_double_t)number->v.s16; case TB_OC_NUMBER_TYPE_UINT32: return (tb_double_t)number->v.u32; case TB_OC_NUMBER_TYPE_SINT32: return (tb_double_t)number->v.s32; case TB_OC_NUMBER_TYPE_UINT64: return (tb_double_t)number->v.u64; case TB_OC_NUMBER_TYPE_SINT64: return (tb_double_t)number->v.s64; default: break; } tb_assert(0); return 0; }
tb_void_t gb_mesh_edge_list_kill(gb_mesh_edge_list_ref_t list, gb_mesh_edge_ref_t edge) { // check gb_mesh_edge_list_impl_t* impl = (gb_mesh_edge_list_impl_t*)list; tb_assert_and_check_return(impl && impl->pool && edge); // make sure the edge points to the first half-edge if (edge->sym < edge) edge = edge->sym; #ifdef __gb_debug__ // check tb_assert(edge->id && edge->sym->id); // clear id edge->id = 0; edge->sym->id = 0; #endif // remove it from the list gb_mesh_edge_remove_done(edge); // exit it tb_fixed_pool_free(impl->pool, edge); }
static tb_size_t tb_vector_remove_last_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_volatile__ tb_size_t i = 0; __tb_volatile__ tb_size_t n = 10000; tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n); tb_hong_t t = tb_mclock(); for (i = 0; i < n; i++) tb_vector_remove_last(vector); t = tb_mclock() - t; // time tb_trace_i("tb_vector_remove_last(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector)); // check tb_assert(!tb_vector_size(vector)); // exit tb_vector_exit(vector); return n / ((tb_uint32_t)(t) + 1); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_double_t tb_exp1(tb_double_t x) { tb_assert(x >= -1 && x <= 1); return (1 + (x) + ((x) * (x)) / 2 + ((x) * (x) * (x)) / 6); }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_float_t tb_expif(tb_long_t x) { tb_assert(x >= -31 && x <= 31); // x = [-31, 31] static tb_float_t table[47] = { // [-15, -1] 0.000000f , 0.000001f , 0.000002f , 0.000006f , 0.000017f , 0.000045f , 0.000123f , 0.000335f , 0.000912f , 0.002479f , 0.006738f , 0.018316f , 0.049787f , 0.135335f , 0.367879f // 0 , 1.000000f // [1, 31] , 2.718282f , 7.389056f , 20.085537f , 54.598150f , 148.413159f , 403.428793f , 1096.633158f , 2980.957987f , 8103.083928f , 22026.465795f , 59874.141715f , 162754.791419f , 442413.392009f , 1202604.284165f , 3269017.372472f , 8886110.520508f , 24154952.753575f , 65659969.137331f , 178482300.963187f , 485165195.409790f , 1318815734.483215f , 3584912846.131592f , 9744803446.248903f , 26489122129.843472f , 72004899337.385880f , 195729609428.838776f , 532048240601.798645f , 1446257064291.475098f , 3931334297144.041992f , 10686474581524.462891f , 29048849665247.425781f }; return table[((x) + 15) & 0x3f]; }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_bool_t xm_os_find_walk(tb_char_t const* path, tb_file_info_t const* info, tb_cpointer_t priv) { // check tb_value_ref_t tuple = (tb_value_ref_t)priv; tb_assert_and_check_return_val(path && info && tuple, tb_false); // the lua lua_State* lua = (lua_State*)tuple[0].ptr; tb_assert_and_check_return_val(lua, tb_false); // the pattern tb_char_t const* pattern = (tb_char_t const*)tuple[1].cstr; tb_assert_and_check_return_val(pattern, tb_false); // find directory? tb_bool_t findir = tuple[2].b; // the count tb_size_t* pcount = &(tuple[3].ul); // trace tb_trace_d("path[%c]: %s", info->type == TB_FILE_TYPE_DIRECTORY? 'd' : 'f', path); // find file or directory? if ((findir && info->type == TB_FILE_TYPE_DIRECTORY) || (!findir && info->type == TB_FILE_TYPE_FILE)) { // done path:match(pattern) lua_getfield(lua, -1, "match"); lua_pushstring(lua, path); lua_pushstring(lua, pattern); if (lua_pcall(lua, 2, 1, 0)) { // trace tb_printf("error: call string.match(%s, %s) failed: %s!\n", path, pattern, lua_tostring(lua, -1)); // failed return tb_false; } // match ok? if (lua_isstring(lua, -1) && !tb_strcmp(path, lua_tostring(lua, -1))) { // exists excludes? tb_bool_t excluded = tb_false; if (lua_istable(lua, 5)) { // the root directory size_t rootlen = 0; tb_char_t const* rootdir = luaL_checklstring(lua, 1, &rootlen); tb_assert_and_check_return_val(rootdir && rootlen, tb_false); // check tb_assert(!tb_strcmp(path, rootdir)); tb_assert(rootlen + 1 <= tb_strlen(path)); // skip the rootdir path += rootlen + 1; // exclude pathes tb_size_t i = 0; tb_size_t count = luaL_getn(lua, 5); for (i = 0; i < count && !excluded; i++) { // get exclude lua_rawgeti(lua, 5, i + 1); tb_char_t const* exclude = lua_tostring(lua, -1); if (exclude) { // done path:match(exclude) lua_getfield(lua, -3, "match"); lua_pushstring(lua, path); lua_pushstring(lua, exclude); if (lua_pcall(lua, 2, 1, 0)) { // trace tb_printf("error: call string.match(%s, %s) failed: %s!\n", path, exclude, lua_tostring(lua, -1)); } // matched? excluded = lua_isstring(lua, -1) && !tb_strcmp(path, lua_tostring(lua, -1)); // pop the match result lua_pop(lua, 1); } // pop exclude lua_pop(lua, 1); } } // save this path if (!excluded) lua_rawseti(lua, -3, ++*pcount); // pop this return value else lua_pop(lua, 1); } // pop this return value else lua_pop(lua, 1); } // continue return tb_true; }
easy_spin_locker(easy_atomic_t *_lock) : lock(_lock) { tb_assert(lock!=NULL) easy_spin_lock(lock); }
tb_bool_t tb_lo_scheduler_start(tb_lo_scheduler_t* scheduler, tb_lo_coroutine_func_t func, tb_cpointer_t priv, tb_lo_coroutine_free_t free) { // check tb_assert(func); // done tb_bool_t ok = tb_false; tb_lo_coroutine_t* coroutine = tb_null; do { // trace tb_trace_d("start .."); // get the current scheduler if (!scheduler) scheduler = (tb_lo_scheduler_t*)tb_lo_scheduler_self_(); tb_assert_and_check_break(scheduler); // have been stopped? do not continue to start new coroutines tb_check_break(!scheduler->stopped); // reuses dead coroutines in init function if (tb_list_entry_size(&scheduler->coroutines_dead)) { // get the next entry from head tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); tb_assert_and_check_break(entry); // remove it from the ready coroutines tb_list_entry_remove_head(&scheduler->coroutines_dead); // get the dead coroutine coroutine = (tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry); // reinit this coroutine tb_lo_coroutine_reinit(coroutine, func, priv, free); } // init coroutine if (!coroutine) coroutine = tb_lo_coroutine_init((tb_lo_scheduler_ref_t)scheduler, func, priv, free); tb_assert_and_check_break(coroutine); // ready coroutine tb_lo_scheduler_make_ready(scheduler, coroutine); // the dead coroutines is too much? free some coroutines while (tb_list_entry_size(&scheduler->coroutines_dead) > TB_SCHEDULER_DEAD_CACHE_MAXN) { // get the next entry from head tb_list_entry_ref_t entry = tb_list_entry_head(&scheduler->coroutines_dead); tb_assert(entry); // remove it from the ready coroutines tb_list_entry_remove_head(&scheduler->coroutines_dead); // exit this coroutine tb_lo_coroutine_exit((tb_lo_coroutine_t*)tb_list_entry(&scheduler->coroutines_dead, entry)); } // ok ok = tb_true; } while (0); // trace tb_trace_d("start %s", ok? "ok" : "no"); // ok? return ok; }
static tb_long_t tb_aiop_rtor_epoll_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout) { // check tb_aiop_rtor_epoll_impl_t* impl = (tb_aiop_rtor_epoll_impl_t*)rtor; tb_assert_and_check_return_val(impl && impl->epfd > 0, -1); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, -1); // init grow tb_size_t grow = tb_align8((rtor->aiop->maxn >> 3) + 1); // init events if (!impl->evts) { impl->evtn = grow; impl->evts = tb_nalloc0(impl->evtn, sizeof(struct epoll_event)); tb_assert_and_check_return_val(impl->evts, -1); } // wait events tb_long_t evtn = epoll_wait(impl->epfd, impl->evts, impl->evtn, timeout); // interrupted?(for gdb?) continue it if (evtn < 0 && errno == EINTR) return 0; // check error? tb_assert_and_check_return_val(evtn >= 0 && evtn <= impl->evtn, -1); // timeout? tb_check_return_val(evtn, 0); // grow it if events is full if (evtn == impl->evtn) { // grow size impl->evtn += grow; if (impl->evtn > rtor->aiop->maxn) impl->evtn = rtor->aiop->maxn; // grow data impl->evts = tb_ralloc(impl->evts, impl->evtn * sizeof(struct epoll_event)); tb_assert_and_check_return_val(impl->evts, -1); } tb_assert(evtn <= impl->evtn); // limit evtn = tb_min(evtn, maxn); // sync tb_size_t i = 0; tb_size_t wait = 0; for (i = 0; i < evtn; i++) { // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)tb_u2p(impl->evts[i].data.u64); tb_assert_and_check_return_val(aioo, -1); // the sock tb_socket_ref_t sock = aioo->sock; tb_assert_and_check_return_val(sock, -1); // the events tb_size_t events = impl->evts[i].events; // spak? if (sock == aiop->spak[1] && (events & EPOLLIN)) { // read spak tb_char_t spak = '\0'; if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) return -1; // killed? if (spak == 'k') return -1; // continue it continue ; } // skip spak tb_check_continue(sock != aiop->spak[1]); // save aioe tb_aioe_ref_t aioe = &list[wait++]; aioe->code = TB_AIOE_CODE_NONE; aioe->priv = aioo->priv; aioe->aioo = (tb_aioo_ref_t)aioo; if (events & EPOLLIN) { aioe->code |= TB_AIOE_CODE_RECV; if (aioo->code & TB_AIOE_CODE_ACPT) aioe->code |= TB_AIOE_CODE_ACPT; } if (events & EPOLLOUT) { aioe->code |= TB_AIOE_CODE_SEND; if (aioo->code & TB_AIOE_CODE_CONN) aioe->code |= TB_AIOE_CODE_CONN; } if (events & (EPOLLHUP | EPOLLERR) && !(aioe->code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND))) aioe->code |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND; // oneshot? clear it if (aioo->code & TB_AIOE_CODE_ONESHOT) { // clear code aioo->code = TB_AIOE_CODE_NONE; aioo->priv = tb_null; // clear events manually if no epoll oneshot #ifndef EPOLLONESHOT struct epoll_event e = {0}; if (epoll_ctl(impl->epfd, EPOLL_CTL_DEL, tb_sock2fd(aioo->sock), &e) < 0) { // trace tb_trace_e("clear aioo[%p] failed manually for oneshot, error: %d", aioo, errno); } #endif } } // ok return wait; }
tb_iterator_ref_t tb_ifaddrs_itor(tb_ifaddrs_ref_t ifaddrs, tb_bool_t reload) { // check tb_list_ref_t interfaces = (tb_list_ref_t)ifaddrs; tb_assert_and_check_return_val(interfaces, tb_null); // uses the cached interfaces? tb_check_return_val(reload, (tb_iterator_ref_t)interfaces); // clear interfaces first tb_list_clear(interfaces); // query the list of interfaces. struct ifaddrs* list = tb_null; if (!getifaddrs(&list) && list) { #if 0 // init sock tb_long_t sock = socket(AF_INET, SOCK_DGRAM, 0); #endif // done struct ifaddrs* item = tb_null; for (item = list; item; item = item->ifa_next) { // check tb_check_continue(item->ifa_addr && item->ifa_name); /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, item->ifa_name); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // done switch (item->ifa_addr->sa_family) { case AF_INET: { // the address struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr; // save ipaddr4 tb_ipaddr_t ipaddr4; if (!tb_sockaddr_save(&ipaddr4, addr)) break; interface->ipaddr4 = ipaddr4.u.ipv4; // save flags interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr4)) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; #if 0 // no hwaddr? get it if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // attempt get the hwaddr struct ifreq ifr; tb_memset(&ifr, 0, sizeof(ifr)); tb_strcpy(ifr.ifr_name, item->ifa_name); if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { // have hwaddr interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; // save hwaddr tb_memcpy(interface->hwaddr.u8, ifr.ifr_hwaddr.sa_data, sizeof(interface->hwaddr.u8)); } } #endif // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(item->ifa_name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } break; case AF_INET6: { // the address struct sockaddr_storage const* addr = (struct sockaddr_storage const*)item->ifa_addr; // save ipaddr6 tb_ipaddr_t ipaddr6; if (!tb_sockaddr_save(&ipaddr6, addr)) break; interface->ipaddr6 = ipaddr6.u.ipv6; // save flags interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; if ((item->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr6)) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; #if 0 // no hwaddr? get it if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // attempt get the hwaddr struct ifreq ifr; tb_memset(&ifr, 0, sizeof(ifr)); tb_strcpy(ifr.ifr_name, item->ifa_name); if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { // have hwaddr interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; // save hwaddr tb_memcpy(interface->hwaddr.u8, ifr.ifr_hwaddr.sa_data, sizeof(interface->hwaddr.u8)); } } #endif // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(item->ifa_name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } break; case AF_PACKET: { // the address struct sockaddr_ll const* addr = (struct sockaddr_ll const*)item->ifa_addr; // check tb_check_break(addr->sll_halen == sizeof(interface->hwaddr.u8)); // no hwaddr? get it if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // have hwaddr interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; // save hwaddr tb_memcpy(interface->hwaddr.u8, addr->sll_addr, sizeof(interface->hwaddr.u8)); // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(item->ifa_name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } } break; default: { // trace tb_trace_d("unknown family: %d", item->ifa_addr->sa_family); } break; } } #if 0 // exit socket if (sock) close(sock); sock = 0; #endif // exit the interface list freeifaddrs(list); } // ok? return (tb_iterator_ref_t)interfaces; }
tb_bool_t tb_timer_spak(tb_timer_ref_t timer) { // check tb_timer_impl_t* impl = (tb_timer_impl_t*)timer; tb_assert_and_check_return_val(impl && impl->pool && impl->heap, tb_false); // stoped? tb_check_return_val(!tb_atomic_get(&impl->stop), tb_false); // enter tb_spinlock_enter(&impl->lock); // done tb_bool_t ok = tb_false; tb_timer_task_func_t func = tb_null; tb_cpointer_t priv = tb_null; tb_bool_t killed = tb_false; do { // empty? if (!tb_heap_size(impl->heap)) { ok = tb_true; break; } // the top task tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)tb_heap_top(impl->heap); tb_assert_and_check_break(task_impl); // check refn tb_assert(task_impl->refn); // the now tb_hong_t now = tb_timer_now(impl); // timeout? if (task_impl->when <= now) { // pop it tb_heap_pop(impl->heap); // save func and data for calling it later func = task_impl->func; priv = task_impl->priv; // killed? killed = task_impl->killed? tb_true : tb_false; // repeat? if (task_impl->repeat) { // update when task_impl->when = now + task_impl->period; // continue task_impl tb_heap_put(impl->heap, task_impl); } else { // refn-- if (task_impl->refn > 1) task_impl->refn--; // remove it from pool directly else tb_fixed_pool_free(impl->pool, task_impl); } } // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&impl->lock); // done func if (func) func(killed, priv); // ok? return ok; }
static tb_void_t gb_window_sdl_loop(gb_window_ref_t window) { // check gb_window_sdl_impl_t* impl = (gb_window_sdl_impl_t*)window; tb_assert_and_check_return(impl); // init canvas if (!impl->canvas) impl->canvas = gb_canvas_init_from_window(window); tb_assert(impl->canvas); // done init if (impl->base.info.init && !impl->base.info.init((gb_window_ref_t)impl, impl->canvas, impl->base.info.priv)) return ; // loop SDL_Event evet; tb_hong_t time; tb_bool_t stop = tb_false; tb_size_t delay = 1000 / (impl->base.info.framerate? impl->base.info.framerate : GB_WINDOW_DEFAULT_FRAMERATE); while (!stop) { // spak time = gb_window_impl_spak((gb_window_ref_t)impl); // lock the surface SDL_LockSurface(impl->surface); // draw gb_window_impl_draw((gb_window_ref_t)impl, impl->canvas); // unlock the surface SDL_UnlockSurface(impl->surface); // flip if (SDL_Flip(impl->surface) < 0) stop = tb_true; // poll while (SDL_PollEvent(&evet)) { // done switch (evet.type) { case SDL_MOUSEMOTION: { // init event gb_event_t event = {0}; event.type = GB_EVENT_TYPE_MOUSE; event.u.mouse.code = GB_MOUSE_MOVE; event.u.mouse.button = impl->button; gb_point_imake(&event.u.mouse.cursor, evet.motion.x, evet.motion.y); // done event gb_window_impl_event((gb_window_ref_t)impl, &event); } break; case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: { // init event gb_event_t event = {0}; event.type = GB_EVENT_TYPE_MOUSE; event.u.mouse.code = evet.type == SDL_MOUSEBUTTONDOWN? GB_MOUSE_DOWN : GB_MOUSE_UP; gb_point_imake(&event.u.mouse.cursor, evet.button.x, evet.button.y); // init button switch (evet.button.button) { case SDL_BUTTON_LEFT: event.u.mouse.button = GB_MOUSE_BUTTON_LEFT; break; case SDL_BUTTON_RIGHT: event.u.mouse.button = GB_MOUSE_BUTTON_RIGHT; break; case SDL_BUTTON_MIDDLE: event.u.mouse.button = GB_MOUSE_BUTTON_MIDDLE; break; default: event.u.mouse.button = GB_MOUSE_BUTTON_NONE; break; } // save button impl->button = evet.type == SDL_MOUSEBUTTONDOWN? event.u.mouse.button : GB_MOUSE_BUTTON_NONE; // done event gb_window_impl_event((gb_window_ref_t)impl, &event); } break; case SDL_KEYDOWN: case SDL_KEYUP: { // init event gb_event_t event = {0}; event.type = GB_EVENT_TYPE_KEYBOARD; event.u.keyboard.pressed = evet.type == SDL_KEYDOWN? tb_true : tb_false; // init code switch ((tb_size_t)evet.key.keysym.sym) { case SDLK_F1: event.u.keyboard.code = GB_KEY_F1; break; case SDLK_F2: event.u.keyboard.code = GB_KEY_F2; break; case SDLK_F3: event.u.keyboard.code = GB_KEY_F3; break; case SDLK_F4: event.u.keyboard.code = GB_KEY_F4; break; case SDLK_F5: event.u.keyboard.code = GB_KEY_F5; break; case SDLK_F6: event.u.keyboard.code = GB_KEY_F6; break; case SDLK_F7: event.u.keyboard.code = GB_KEY_F7; break; case SDLK_F8: event.u.keyboard.code = GB_KEY_F8; break; case SDLK_F9: event.u.keyboard.code = GB_KEY_F9; break; case SDLK_F10: event.u.keyboard.code = GB_KEY_F10; break; case SDLK_F11: event.u.keyboard.code = GB_KEY_F11; break; case SDLK_F12: event.u.keyboard.code = GB_KEY_F12; break; case SDLK_LEFT: event.u.keyboard.code = GB_KEY_LEFT; break; case SDLK_UP: event.u.keyboard.code = GB_KEY_UP; break; case SDLK_RIGHT: event.u.keyboard.code = GB_KEY_RIGHT; break; case SDLK_DOWN: event.u.keyboard.code = GB_KEY_DOWN; break; case SDLK_HOME: event.u.keyboard.code = GB_KEY_HOME; break; case SDLK_END: event.u.keyboard.code = GB_KEY_END; break; case SDLK_INSERT: event.u.keyboard.code = GB_KEY_INSERT; break; case SDLK_PAGEUP: event.u.keyboard.code = GB_KEY_PAGEUP; break; case SDLK_PAGEDOWN: event.u.keyboard.code = GB_KEY_PAGEDOWN; break; case SDLK_HELP: event.u.keyboard.code = GB_KEY_HELP; break; case SDLK_PRINT: event.u.keyboard.code = GB_KEY_PRINT; break; case SDLK_SYSREQ: event.u.keyboard.code = GB_KEY_SYSREQ; break; case SDLK_BREAK: event.u.keyboard.code = GB_KEY_BREAK; break; case SDLK_MENU: event.u.keyboard.code = GB_KEY_MENU; break; case SDLK_POWER: event.u.keyboard.code = GB_KEY_POWER; break; case SDLK_EURO: event.u.keyboard.code = GB_KEY_EURO; break; case SDLK_UNDO: event.u.keyboard.code = GB_KEY_UNDO; break; case SDLK_NUMLOCK: event.u.keyboard.code = GB_KEY_NUMLOCK; break; case SDLK_CAPSLOCK: event.u.keyboard.code = GB_KEY_CAPSLOCK; break; case SDLK_SCROLLOCK: event.u.keyboard.code = GB_KEY_SCROLLLOCK; break; case SDLK_RSHIFT: event.u.keyboard.code = GB_KEY_RSHIFT; break; case SDLK_LSHIFT: event.u.keyboard.code = GB_KEY_LSHIFT; break; case SDLK_RCTRL: event.u.keyboard.code = GB_KEY_RCTRL; break; case SDLK_LCTRL: event.u.keyboard.code = GB_KEY_LCTRL; break; case SDLK_RALT: event.u.keyboard.code = GB_KEY_RALT; break; case SDLK_LALT: event.u.keyboard.code = GB_KEY_LALT; break; case 0x136: event.u.keyboard.code = GB_KEY_RCMD; break; case 0x135: event.u.keyboard.code = GB_KEY_LCMD; break; case SDLK_PAUSE: event.u.keyboard.code = GB_KEY_PAUSE; break; default : if (evet.key.keysym.sym < 256) { // the char code event.u.keyboard.code = evet.key.keysym.sym; } break; } // done event if (event.u.keyboard.code) gb_window_impl_event((gb_window_ref_t)impl, &event); } break; case SDL_VIDEORESIZE: { // trace tb_trace_d("resize: type: %d, %dx%d", evet.resize.type, evet.resize.w, evet.resize.h); // TODO // ... } break; case SDL_ACTIVEEVENT: { // trace tb_trace_d("active: type: %d, gain: %d, state: %d", evet.active.type, evet.active.gain, evet.active.state); // active? if (evet.active.state == SDL_APPACTIVE) { // init event gb_event_t event = {0}; event.type = GB_EVENT_TYPE_ACTIVE; event.u.active.code = evet.active.gain? GB_ACTIVE_FOREGROUND : GB_ACTIVE_BACKGROUND; // done event gb_window_impl_event((gb_window_ref_t)impl, &event); } } break; case SDL_QUIT: { // stop it stop = tb_true; } break; default: // trace tb_trace_e("unknown event: %x", evet.type); break; } } // compute the delta time time = tb_cache_time_spak() - time; // wait if (delay > (tb_size_t)time) SDL_Delay(delay - (tb_size_t)time); } // done exit if (impl->base.info.exit) impl->base.info.exit((gb_window_ref_t)impl, impl->canvas, impl->base.info.priv); }
static tb_void_t gb_window_sdl_fullscreen(gb_window_ref_t window, tb_bool_t fullscreen) { // check gb_window_sdl_impl_t* impl = (gb_window_sdl_impl_t*)window; tb_assert_and_check_return(impl); // the pixmap gb_pixmap_ref_t pixmap = gb_pixmap(impl->base.pixfmt, 0xff); tb_assert_and_check_return(pixmap); // fullscreen? tb_size_t changed = tb_false; if (fullscreen && !(impl->base.flag & GB_WINDOW_FLAG_FULLSCREEN)) { // exit surface if (impl->surface) SDL_FreeSurface(impl->surface); // init mode tb_size_t mode = SDL_DOUBLEBUF | SDL_FULLSCREEN; // TODO // the screen width and height tb_uint16_t screen_width = 0;//tb_screen_width(); tb_uint16_t screen_height = 0;//tb_screen_height(); tb_assert(screen_width && screen_height && screen_width <= GB_WIDTH_MAXN && screen_height <= GB_HEIGHT_MAXN); // init surface impl->surface = SDL_SetVideoMode(screen_width, screen_height, pixmap->bpp, mode | SDL_HWSURFACE); if (!impl->surface) impl->surface = SDL_SetVideoMode(screen_width, screen_height, pixmap->bpp, mode | SDL_SWSURFACE); tb_assert(impl->surface && impl->surface->pixels); // update flag impl->base.flag |= GB_WINDOW_FLAG_FULLSCREEN; // save the normal width and height impl->normal_width = (tb_uint16_t)gb_window_width(window); impl->normal_height = (tb_uint16_t)gb_window_height(window); // update the window width and height impl->base.width = screen_width; impl->base.height = screen_height; // changed changed = tb_true; } else if (impl->base.flag & GB_WINDOW_FLAG_FULLSCREEN) { // exit surface if (impl->surface) SDL_FreeSurface(impl->surface); // init mode tb_size_t mode = SDL_DOUBLEBUF; if (impl->base.flag & GB_WINDOW_FLAG_HIHE_TITLEBAR) mode |= SDL_NOFRAME; if (impl->base.flag & GB_WINDOW_FLAG_NOT_REISZE) mode &= ~SDL_RESIZABLE; else mode |= SDL_RESIZABLE; // init surface impl->surface = SDL_SetVideoMode(impl->normal_width, impl->normal_height, pixmap->bpp, mode | SDL_HWSURFACE); if (!impl->surface) impl->surface = SDL_SetVideoMode(impl->normal_width, impl->normal_height, pixmap->bpp, mode | SDL_SWSURFACE); tb_assert(impl->surface && impl->surface->pixels); // update flag impl->base.flag &= ~GB_WINDOW_FLAG_FULLSCREEN; // update the window width and height impl->base.width = impl->normal_width; impl->base.height = impl->normal_height; // changed changed = tb_true; } // ok? if (changed) { // exit canvas first if (impl->canvas) gb_canvas_exit(impl->canvas); // exit bitmap first if (impl->base.bitmap) tb_free(impl->base.bitmap); // init bitmap impl->base.bitmap = gb_bitmap_init(impl->surface->pixels, impl->base.pixfmt, impl->base.width, impl->base.height, impl->surface->pitch, tb_false); tb_assert(impl->base.bitmap); // init canvas impl->canvas = gb_canvas_init_from_window(window); tb_assert(impl->canvas); // done resize if (impl->base.info.resize) impl->base.info.resize((gb_window_ref_t)impl, impl->canvas, impl->base.info.priv); } }
static tb_void_t tb_element_null_nrepl(tb_element_ref_t element, tb_pointer_t buff, tb_cpointer_t data, tb_size_t size) { tb_assert(data == tb_null); }
/* ////////////////////////////////////////////////////////////////////////////////////// * private implementation */ static tb_pool_data_empty_head_t* tb_static_fixed_pool_malloc_pred(tb_static_fixed_pool_t* pool) { // check tb_assert_and_check_return_val(pool, tb_null); // done tb_pool_data_empty_head_t* data_head = tb_null; do { // exists the predict index? tb_check_break(pool->pred_index); // the predict index tb_size_t pred_index = pool->pred_index - 1; tb_assert((pred_index << TB_CPU_SHIFT) < pool->item_maxn); // the predict data tb_size_t* data = (tb_size_t*)pool->used_info + pred_index; // full? tb_check_break((*data) + 1); // the free bit index tb_size_t index = (pred_index << TB_CPU_SHIFT) + tb_static_fixed_pool_find_free(*data); // out of range? if (index >= pool->item_maxn) { // clear the pred index pool->pred_index = 0; break; } // check tb_assert(!tb_static_fixed_pool_used_bset(pool->used_info, index)); // the data head data_head = (tb_pool_data_empty_head_t*)(pool->data + index * pool->item_space); // allocate it tb_static_fixed_pool_used_set1(pool->used_info, index); // the predict data is full if (!((*data) + 1)) { // clear the predict index pool->pred_index = 0; // predict the next index if (index + 1 < pool->item_maxn && !tb_static_fixed_pool_used_bset(pool->used_info, index + 1)) tb_static_fixed_pool_cache_pred(pool, index + 1); } } while (0); #ifdef __tb_debug__ // update the predict failed count if (!data_head) pool->pred_failed++; #endif // ok? return data_head; }
static tb_pointer_t tb_database_sqlite3_result_col_iterator_item(tb_iterator_ref_t iterator, tb_size_t itor) { // check tb_database_sqlite3_result_row_t* row = (tb_database_sqlite3_result_row_t*)iterator; tb_assert_and_check_return_val(row && itor < row->count, tb_null); // the sqlite tb_database_sqlite3_t* sqlite = (tb_database_sqlite3_t*)iterator->priv; tb_assert_and_check_return_val(sqlite, tb_null); // result? if (sqlite->result.result) { // init value tb_database_sql_value_name_set(&row->value, (tb_char_t const*)sqlite->result.result[itor]); tb_database_sql_value_set_text(&row->value, (tb_char_t const*)sqlite->result.result[((1 + sqlite->result.row.row) * row->count) + itor], 0); return (tb_pointer_t)&row->value; } // statement result? else if (sqlite->result.statement) { // init name tb_database_sql_value_name_set(&row->value, sqlite3_column_name(sqlite->result.statement, (tb_int_t)itor)); // init type tb_size_t type = sqlite3_column_type(sqlite->result.statement, (tb_int_t)itor); switch (type) { case SQLITE_INTEGER: tb_database_sql_value_set_int32(&row->value, sqlite3_column_int(sqlite->result.statement, (tb_int_t)itor)); break; case SQLITE_TEXT: tb_database_sql_value_set_text(&row->value, (tb_char_t const*)sqlite3_column_text(sqlite->result.statement, (tb_int_t)itor), sqlite3_column_bytes(sqlite->result.statement, (tb_int_t)itor)); break; case SQLITE_FLOAT: #ifdef TB_CONFIG_TYPE_HAVE_FLOAT tb_database_sql_value_set_double(&row->value, sqlite3_column_double(sqlite->result.statement, (tb_int_t)itor)); break; #else // trace tb_trace1_e("float type is not supported, at col: %lu, please enable float config!", itor); return tb_null; #endif case SQLITE_BLOB: tb_database_sql_value_set_blob32(&row->value, (tb_byte_t const*)sqlite3_column_blob(sqlite->result.statement, (tb_int_t)itor), sqlite3_column_bytes(sqlite->result.statement, (tb_int_t)itor), tb_null); break; case SQLITE_NULL: tb_database_sql_value_set_null(&row->value); break; default: tb_trace_e("unknown field type: %s, at col: %lu", type, itor); return tb_null; } // ok return (tb_pointer_t)&row->value; } // failed tb_assert(0); return tb_null; }
static tb_bool_t it_find_symtab_addrs(mach_vm_address_t dyldImageLoadAddress, tb_uint32_t ncmds, mach_vm_size_t sizeofcmds, struct load_command* cmds, tb_bool_t swap, tb_size_t nlist_size, it_symtab_bundle_t* symtab, mach_vm_address_t* slide_) { // init offset tb_uint32_t symoff = 0; tb_uint32_t stroff = 0; // clear memset(symtab, 0, sizeof(*symtab)); // walk mach_vm_address_t vma = 0; struct load_command* lc = cmds; tb_size_t ln = ncmds; while (ln--) { tb_uint32_t cmdsize = it_swap_u32(lc->cmdsize); tb_assert(sizeofcmds >= sizeof(struct load_command) && sizeofcmds >= cmdsize); sizeofcmds -= cmdsize; if (!vma && it_swap_u32(lc->cmd) == LC_SEGMENT) { struct segment_command* sc = (tb_pointer_t) lc; tb_assert(cmdsize >= sizeof(*sc)); vma = it_swap_u32(sc->vmaddr); } else if (!vma && it_swap_u32(lc->cmd) == LC_SEGMENT_64) { struct segment_command_64* sc = (tb_pointer_t) lc; tb_assert(cmdsize >= sizeof(*sc)); vma = it_swap_u64(sc->vmaddr); } else if (it_swap_u32(lc->cmd) == LC_SYMTAB) { struct symtab_command* sc = (tb_pointer_t) lc; tb_assert(cmdsize >= sizeof(*sc)); symoff = it_swap_u32(sc->symoff); symtab->nsyms = it_swap_u32(sc->nsyms); stroff = it_swap_u32(sc->stroff); symtab->strsize = it_swap_u32(sc->strsize); tb_assert(symtab->strsize < 10000000 && symtab->nsyms < 10000000); } // next lc = (tb_pointer_t) ((tb_char_t*) lc + it_swap_u32(lc->cmdsize)); } // check tb_assert_and_check_return_val(symoff && vma, tb_false); // slide mach_vm_address_t slide = dyldImageLoadAddress - vma; *slide_ = slide; // walk lc = cmds; ln = ncmds; while (ln--) { #define CATCH(SWAP, off, size, addr) tb_assert(SWAP(sc->fileoff) + SWAP(sc->filesize) >= SWAP(sc->fileoff)); if (SWAP(sc->fileoff) <= (off) && (SWAP(sc->fileoff) + SWAP(sc->filesize) - (off)) >= (size)) (addr) = SWAP(sc->vmaddr) + slide + (off) - SWAP(sc->fileoff); if (it_swap_u32(lc->cmd) == LC_SEGMENT) { struct segment_command* sc = (tb_pointer_t) lc; if(!vma) vma = it_swap_u32(sc->vmaddr); CATCH(it_swap_u32, symoff, symtab->nsyms * nlist_size, symtab->symaddr); CATCH(it_swap_u32, stroff, symtab->strsize, symtab->straddr); } else if (it_swap_u32(lc->cmd) == LC_SEGMENT_64) { struct segment_command_64* sc = (tb_pointer_t) lc; CATCH(it_swap_u64, symoff, symtab->nsyms * nlist_size, symtab->symaddr); CATCH(it_swap_u64, stroff, symtab->strsize, symtab->straddr); } lc = (tb_pointer_t) ((tb_char_t*)lc + it_swap_u32(lc->cmdsize)); } tb_assert(symtab->straddr); tb_assert(symtab->symaddr); // ok return tb_true; }
void tdhs_dbcontext::open_table(tdhs_request_t &req) { //MARK 针对request type 需要进行判断,不需要open table的直接退出 if (req.type == REQUEST_TYPE_BATCH) { return; } if (pool_for_open_table == NULL) { pool_for_open_table = easy_pool_create(MAX_POOL_SIZE_FOR_OPEN_TABLE); } if (already_cached_table_num > 0) { tb_assert(already_cached_table_num<=cache_table_num); for (unsigned int i = 0; i < already_cached_table_num; i++) { cached_table_t &cached_t = cached_table[i]; if (cached_t.table != NULL) { TABLE* t = cached_t.table; opened_table_t& opened_t = for_cached_opened_table[i]; opened_t.mysql_table = t; easy_hash_add(hash_table_for_opened, cached_t.hash_code_for_table > 0 ? cached_t.hash_code_for_table : make_hash_code_for_table(t->s->db.str,t->s->db.length,t->s->table_name.str,t->s->table_name.length) , &opened_t.hash); if (opened_table_num < DBCONTEXT_MAX_CACHE_LOCK_TABLES) { need_lock_tables[opened_table_num++] = t; } else { opened_table_num++; } cached_t.table = NULL; //置空 cached_t.hash_code_for_table = 0; //置空 } } already_cached_table_num = 0; //置0 } { opened_table_t * opened_table = (opened_table_t *) easy_hash_find_ex( hash_table_for_opened, req.table_info.hash_code_table(), compare_table_info, &req.table_info); if (opened_table != NULL) { req.opened_table = opened_table; } else { opened_table = (opened_table_t *) easy_pool_calloc( pool_for_open_table, sizeof(opened_table_t)); if (opened_table != NULL) { req.opened_table = opened_table; TABLE* t = tdhs_open_table(thd, req.table_info, this->need_write()); if (t != NULL) { req.opened_table->mysql_table = t; easy_hash_add(hash_table_for_opened, req.table_info.hash_code_table(), &req.opened_table->hash); if (opened_table_num < DBCONTEXT_MAX_CACHE_LOCK_TABLES) { need_lock_tables[opened_table_num++] = t; } else { opened_table_num++; } } } else { //if opened_table==NULL because of memory is not enough easy_error_log( "TDHS:not enough memory for calloc opened_table_t!"); } } } }
static kern_return_t it_stuff(task_t task, cpu_type_t* cputype, it_addr_bundle_t* addrs) { // make the optimizer happy *cputype = 0; // init the task info task_dyld_info_data_t info = {0}; mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; if (task_info(task, TASK_DYLD_INFO, (task_info_t) &info, &count)) return tb_false; // read all image info union { it_dyld_all_image_infos_t data; it_dyld_all_image_infos_64_t data64; } u; mach_vm_size_t data_size = sizeof(u); if (info.all_image_info_size < data_size) data_size = info.all_image_info_size; if (mach_vm_read_overwrite(task, info.all_image_info_addr, data_size, it_address_cast(&u), &data_size)) return tb_false; if (u.data.version <= 1) return tb_false; // read mach header #if defined(TB_ARCH_x86) || defined(TB_ARCH_x64) || defined(TB_ARCH_ARM64) tb_bool_t proc64 = u.data64.dyldImageLoadAddress > 0? tb_true : tb_false; #else tb_bool_t proc64 = tb_false; #endif tb_trace_d("proc64: %p", proc64); struct mach_header mach_hdr = {0}; mach_vm_address_t dyldImageLoadAddress = proc64? u.data64.dyldImageLoadAddress : u.data.dyldImageLoadAddress; if (mach_vm_read_overwrite(task, dyldImageLoadAddress, (mach_vm_size_t)sizeof(mach_hdr), it_address_cast(&mach_hdr), &data_size)) return tb_false; // swap? tb_bool_t swap = (mach_hdr.magic == MH_CIGAM || mach_hdr.magic == MH_CIGAM_64)? tb_true : tb_false; tb_trace_d("swap: %u", swap); // save sputype *cputype = it_swap_u32(mach_hdr.cputype); // read cmds mach_vm_size_t sizeofcmds = it_swap_u32(mach_hdr.sizeofcmds); struct load_command* cmds = malloc(sizeofcmds); tb_bool_t mh64 = (mach_hdr.magic == MH_MAGIC_64 || mach_hdr.magic == MH_CIGAM_64)? tb_true : tb_false; tb_trace_d("mh64: %u", mh64); if (mach_vm_read_overwrite(task, dyldImageLoadAddress + (mh64 ? sizeof(struct mach_header_64) : sizeof(struct mach_header)), (mach_vm_size_t)sizeofcmds, it_address_cast(cmds), &sizeofcmds)) return tb_false; // read symtab mach_vm_address_t slide; it_symtab_bundle_t symtab; tb_size_t nlist_size = mh64 ? sizeof(struct nlist_64) : sizeof(struct nlist); if (!it_find_symtab_addrs(dyldImageLoadAddress, mach_hdr.ncmds, sizeofcmds, cmds, swap, nlist_size, &symtab, &slide)) return tb_false; // read strs & syms tb_char_t* strs = malloc(symtab.strsize); tb_pointer_t syms = malloc(symtab.nsyms * nlist_size); if (mach_vm_read_overwrite(task, symtab.straddr, (mach_vm_size_t)(symtab.strsize), it_address_cast(strs), &data_size)) return tb_false; if (mach_vm_read_overwrite(task, symtab.symaddr, (mach_vm_size_t)(symtab.nsyms * nlist_size), it_address_cast(syms), &data_size)) return tb_false; // read address memset(addrs, 0, sizeof(*addrs)); if (mh64) { struct nlist_64 const* nl = syms; while (symtab.nsyms--) { tb_uint32_t strx = (tb_uint32_t) it_swap_u32(nl->n_un.n_strx); tb_assert(strx < symtab.strsize); it_handle_sym(strs + strx, symtab.strsize - strx, (mach_vm_address_t) it_swap_u64(nl->n_value) + slide, addrs); nl++; } } else { struct nlist const* nl = syms; while (symtab.nsyms--) { tb_uint32_t strx = it_swap_u32(nl->n_un.n_strx); tb_assert(strx < symtab.strsize); it_handle_sym(strs + strx, symtab.strsize - strx, (mach_vm_address_t) it_swap_u32(nl->n_value) + slide, addrs); nl++; } } tb_assert(addrs->dlopen); tb_assert(addrs->syscall); // free if (cmds) free(cmds); if (strs) free(strs); if (syms) free(syms); // ok return tb_true; }
static tb_pointer_t tb_aiop_spak_loop(tb_cpointer_t priv) { // check tb_aiop_ptor_impl_t* impl = (tb_aiop_ptor_impl_t*)priv; tb_aicp_impl_t* aicp = impl? impl->base.aicp : tb_null; // done do { // check tb_assert_and_check_break(impl && impl->aiop && impl->list && impl->timer && impl->ltimer && aicp); // trace tb_trace_d("loop: init"); // loop while (!tb_atomic_get(&aicp->kill)) { // the delay tb_size_t delay = tb_timer_delay(impl->timer); // the ldelay tb_size_t ldelay = tb_ltimer_delay(impl->ltimer); tb_assert_and_check_break(ldelay != -1); // trace tb_trace_d("loop: wait: .."); // wait aioe tb_long_t real = tb_aiop_wait(impl->aiop, impl->list, impl->maxn, tb_min(delay, ldelay)); // trace tb_trace_d("loop: wait: %ld", real); // spak ctime tb_cache_time_spak(); // spak timer if (!tb_timer_spak(impl->timer)) break; // spak ltimer if (!tb_ltimer_spak(impl->ltimer)) break; // killed? tb_check_break(real >= 0); // error? out of range tb_assert_and_check_break(real <= impl->maxn); // timeout? tb_check_continue(real); // grow it if aioe is full if (real == impl->maxn) { // grow size impl->maxn += (aicp->maxn >> 4) + 16; if (impl->maxn > aicp->maxn) impl->maxn = aicp->maxn; // grow list impl->list = tb_ralloc(impl->list, impl->maxn * sizeof(tb_aioe_t)); tb_assert_and_check_break(impl->list); } // walk aioe list tb_size_t i = 0; tb_bool_t end = tb_false; for (i = 0; i < real && !end; i++) { // the aioe tb_aioe_ref_t aioe = &impl->list[i]; tb_assert_and_check_break_state(aioe, end, tb_true); // the aice tb_aice_ref_t aice = (tb_aice_ref_t)aioe->priv; tb_assert_and_check_break_state(aice, end, tb_true); // the aico tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico; tb_assert_and_check_break_state(aico, end, tb_true); // have wait? tb_check_continue(aice->code); // have been waited ok for the timer timeout/killed func? need not spak it repeatly tb_check_continue(!aico->wait_ok); // sock? if (aico->base.type == TB_AICO_TYPE_SOCK) { // push the acpt aice if (aice->code == TB_AICE_CODE_ACPT) end = tb_aiop_push_acpt(impl, aice)? tb_false : tb_true; // push the sock aice else end = tb_aiop_push_sock(impl, aice)? tb_false : tb_true; } else if (aico->base.type == TB_AICO_TYPE_FILE) { // poll file tb_aicp_file_poll(impl); } else tb_assert(0); } // end? tb_check_break(!end); // work it tb_aiop_spak_work(impl); } } while (0); // trace tb_trace_d("loop: exit"); // kill tb_aicp_kill((tb_aicp_ref_t)aicp); // exit tb_thread_return(tb_null); return tb_null; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_bool_t gb_tessellator_mesh_make(gb_tessellator_impl_t* impl, gb_polygon_ref_t polygon) { // check tb_assert(impl && polygon); // the points gb_point_ref_t points = polygon->points; tb_uint16_t const* counts = polygon->counts; tb_assert_and_check_return_val(points && counts, tb_false); // not exists mesh? if (!impl->mesh) { // init func tb_element_t edge_element = tb_element_mem(sizeof(gb_tessellator_edge_t), tb_null, tb_null); tb_element_t face_element = tb_element_mem(sizeof(gb_tessellator_face_t), tb_null, tb_null); tb_element_t vertex_element = tb_element_mem(sizeof(gb_tessellator_vertex_t), tb_null, tb_null); #ifdef __gb_debug__ // init func cstr for gb_mesh_dump edge_element.cstr = gb_tessellator_edge_cstr; face_element.cstr = gb_tessellator_face_cstr; vertex_element.cstr = gb_tessellator_vertex_cstr; #endif // init mesh impl->mesh = gb_mesh_init(edge_element, face_element, vertex_element); /* init the order * * the new edges/faces/vertice will be inserted to the head of list */ gb_mesh_edge_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); gb_mesh_face_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); gb_mesh_vertex_order_set(impl->mesh, GB_MESH_ORDER_INSERT_HEAD); // init listener gb_mesh_listener_set(impl->mesh, gb_tessellator_listener, impl->mesh); gb_mesh_listener_event_add(impl->mesh, GB_MESH_EVENT_FACE_SPLIT | GB_MESH_EVENT_EDGE_SPLIT); } // check gb_mesh_ref_t mesh = impl->mesh; tb_assert_and_check_return_val(mesh, tb_false); // clear mesh first gb_mesh_clear(mesh); // done gb_point_ref_t point = tb_null; tb_uint16_t count = *counts++; tb_size_t index = 0; gb_mesh_edge_ref_t edge = tb_null; gb_mesh_edge_ref_t edge_first = tb_null; while (index < count) { // the point point = points++; // first point? if (!index) { // must be closed contour tb_assertf(gb_point_eq(point, point + count - 1), "this contour(%lu: %{point} => %{point}) is not closed!", count, point, point + count - 1); // clear the edge edge = tb_null; // clear the first edge edge_first = tb_null; // trace tb_trace_d("move_to: %{point}", point); } // closed? else if (index + 1 == count) { // trace tb_trace_d("closed: %{point}", point); // connect an edge to the first edge edge = gb_mesh_edge_connect(mesh, edge, edge_first); // init edge.faces.inside gb_tessellator_face_inside_set(gb_mesh_edge_lface(edge), 0); gb_tessellator_face_inside_set(gb_mesh_edge_rface(edge), 0); } else { // trace tb_trace_d("line_to: %{point}", point); // exists the first edge? if (edge_first) { // append an edge edge = gb_mesh_edge_append(mesh, edge); } else { // make a new non-loop edge edge = gb_mesh_edge_make(mesh); // save the first edge edge_first = edge; } } // has new edge? if (edge) { // init edge.winding gb_tessellator_edge_winding_set(edge, 1); gb_tessellator_edge_winding_set(gb_mesh_edge_sym(edge), -1); // init edge.region gb_tessellator_edge_region_set(edge, tb_null); gb_tessellator_edge_region_set(gb_mesh_edge_sym(edge), tb_null); // init edge.dst gb_tessellator_vertex_point_set(gb_mesh_edge_dst(edge), point); } // next point index++; // next polygon if (index == count) { // next count = *counts++; index = 0; } } #ifdef __gb_debug__ // check mesh gb_mesh_check(mesh); #endif // ok? return !gb_mesh_is_empty(mesh); }
tb_bool_t tb_hwaddr_cstr_set(tb_hwaddr_ref_t hwaddr, tb_char_t const* cstr) { // check tb_assert_and_check_return_val(cstr, tb_false); // done tb_uint32_t v = 0; tb_char_t c = '\0'; tb_size_t i = 0; tb_char_t const* p = cstr; tb_bool_t ok = tb_true; tb_hwaddr_t temp; do { // the character c = *p++; // digit? if (tb_isdigit16(c) && v <= 0xff) { // update value if (tb_isdigit10(c)) v = (v << 4) + (c - '0'); else if (c > ('a' - 1) && c < ('f' + 1)) v = (v << 4) + (c - 'a') + 10; else if (c > ('A' - 1) && c < ('F' + 1)) v = (v << 4) + (c - 'A') + 10; else { // abort tb_assert(0); // failed ok = tb_false; break; } } // ':' or "-" or '\0'? else if (i < 6 && (c == ':' || c == '-' || !c) && v <= 0xff) { // save value temp.u8[i++] = v; // clear value v = 0; } // failed? else { ok = tb_false; break; } } while (c); // failed if (i != 6) ok = tb_false; // save it if ok if (ok && hwaddr) *hwaddr = temp; // trace // tb_assertf(ok, "invalid hwaddr: %s", cstr); // ok? return ok; }
static tb_void_t tb_ifaddrs_interface_load6(tb_list_ref_t interfaces) { // check tb_assert_and_check_return(interfaces); // done PIP_ADAPTER_ADDRESSES addresses = tb_null; do { // make the addresses addresses = (PIP_ADAPTER_ADDRESSES)tb_malloc0_type(IP_ADAPTER_ADDRESSES); tb_assert_and_check_break(addresses); // get the real adapter info size ULONG size = sizeof(IP_ADAPTER_ADDRESSES); if (tb_iphlpapi()->GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_DNS_SERVER, tb_null, addresses, &size) == ERROR_BUFFER_OVERFLOW) { // grow the adapter info buffer addresses = (PIP_ADAPTER_ADDRESSES)tb_ralloc(addresses, size); tb_assert_and_check_break(addresses); // reclear it tb_memset(addresses, 0, size); } // get the addresses if (tb_iphlpapi()->GetAdaptersAddresses(AF_INET6, GAA_FLAG_SKIP_DNS_SERVER, tb_null, addresses, &size) != NO_ERROR) break; // done PIP_ADAPTER_ADDRESSES address = addresses; while (address) { // check tb_assert(address->AdapterName); /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, address->AdapterName); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // save flags if (address->IfType == IF_TYPE_SOFTWARE_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; // save hwaddr if (address->PhysicalAddressLength == sizeof(interface->hwaddr.u8)) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; tb_memcpy(interface->hwaddr.u8, address->PhysicalAddress, sizeof(interface->hwaddr.u8)); } // save ipaddrs PIP_ADAPTER_UNICAST_ADDRESS ipAddress = address->FirstUnicastAddress; while (ipAddress && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) { // done tb_ipaddr_t ipaddr; struct sockaddr_storage* saddr = (struct sockaddr_storage*)ipAddress->Address.lpSockaddr; if (saddr && tb_sockaddr_save(&ipaddr, saddr)) { if (ipaddr.family == TB_IPADDR_FAMILY_IPV4) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; interface->ipaddr4 = ipaddr.u.ipv4; } else if (ipaddr.family == TB_IPADDR_FAMILY_IPV6) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; interface->ipaddr6 = ipaddr.u.ipv6; } } // the next ipAddress = ipAddress->Next; } // new interface? save it if ( interface == &interface_new && interface->flags) { // save interface name interface->name = tb_strdup(address->AdapterName); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } // the next address address = address->Next; } } while (0); // exit the addresses if (addresses) tb_free(addresses); addresses = tb_null; }
pthread_mutex_locker(pthread_mutex_t *_lock) : lock(_lock) { tb_assert(lock!=NULL) pthread_mutex_lock(lock); }
static tb_void_t tb_ifaddrs_interface_done_ipaddr(tb_list_ref_t interfaces, tb_hash_map_ref_t names, struct nlmsghdr* response) { // check tb_assert_and_check_return(interfaces && names && response); // the info struct ifaddrmsg* info = (struct ifaddrmsg *)NLMSG_DATA(response); // must be not link tb_assert_and_check_return(info->ifa_family != AF_PACKET); // attempt to find the interface name tb_bool_t owner = tb_false; tb_char_t* name = (tb_char_t*)tb_hash_map_get(names, tb_u2p(info->ifa_index)); if (!name) { // get the interface name struct rtattr* rta = tb_null; tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg)); for(rta = IFA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size)) { // done tb_pointer_t rta_data = RTA_DATA(rta); tb_size_t rta_data_size = RTA_PAYLOAD(rta); switch(rta->rta_type) { case IFA_LABEL: { // make name name = (tb_char_t*)tb_ralloc(name, rta_data_size + 1); tb_assert_and_check_break(name); // copy name tb_strlcpy(name, rta_data, rta_data_size + 1); // save name tb_hash_map_insert(names, tb_u2p(info->ifa_index), name); owner = tb_true; } break; default: break; } } } // check tb_check_return(name); // done struct rtattr* rta = tb_null; tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg)); for(rta = IFA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size)) { /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, name); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // done tb_pointer_t rta_data = RTA_DATA(rta); switch(rta->rta_type) { case IFA_LOCAL: case IFA_ADDRESS: { // make ipaddr tb_ipaddr_t ipaddr; if (!tb_ifaddrs_netlink_ipaddr_save(&ipaddr, info->ifa_family, info->ifa_index, rta_data)) break; // save flags if ((info->ifa_flags & IFF_LOOPBACK) || tb_ipaddr_ip_is_loopback(&ipaddr)) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; // save ipaddr switch (tb_ipaddr_family(&ipaddr)) { case TB_IPADDR_FAMILY_IPV4: { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; interface->ipaddr4 = ipaddr.u.ipv4; } break; case TB_IPADDR_FAMILY_IPV6: { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; interface->ipaddr6 = ipaddr.u.ipv6; } break; default: break; } // trace tb_trace_d("name: %s, ipaddr: %{ipaddr}", name, &ipaddr); // new interface? save it if (tb_ipaddr_family(&ipaddr) && interface == &interface_new) { // save interface name interface->name = tb_strdup(name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } break; case IFA_LABEL: case IFA_BROADCAST: break; default: break; } } // exit name if (name && owner) tb_free(name); name = tb_null; }
static tb_long_t tb_aiop_rtor_kqueue_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_ref_t list, tb_size_t maxn, tb_long_t timeout) { // check tb_aiop_rtor_kqueue_impl_t* impl = (tb_aiop_rtor_kqueue_impl_t*)rtor; tb_assert_and_check_return_val(impl && impl->kqfd >= 0 && rtor->aiop && list && maxn, -1); // the aiop tb_aiop_impl_t* aiop = rtor->aiop; tb_assert_and_check_return_val(aiop, -1); // init time struct timespec t = {0}; if (timeout > 0) { t.tv_sec = timeout / 1000; t.tv_nsec = (timeout % 1000) * 1000000; } // init grow tb_size_t grow = tb_align8((rtor->aiop->maxn >> 3) + 1); // init events if (!impl->evts) { impl->evtn = grow; impl->evts = tb_nalloc0(impl->evtn, sizeof(struct kevent)); tb_assert_and_check_return_val(impl->evts, -1); } // wait events tb_long_t evtn = kevent(impl->kqfd, tb_null, 0, impl->evts, impl->evtn, timeout >= 0? &t : tb_null); tb_assert_and_check_return_val(evtn >= 0 && evtn <= impl->evtn, -1); // timeout? tb_check_return_val(evtn, 0); // grow it if events is full if (evtn == impl->evtn) { // grow size impl->evtn += grow; if (impl->evtn > rtor->aiop->maxn) impl->evtn = rtor->aiop->maxn; // grow data impl->evts = tb_ralloc(impl->evts, impl->evtn * sizeof(struct kevent)); tb_assert_and_check_return_val(impl->evts, -1); } tb_assert(evtn <= impl->evtn); // limit evtn = tb_min(evtn, maxn); // sync tb_size_t i = 0; tb_size_t wait = 0; for (i = 0; i < evtn; i++) { // the kevents struct kevent* e = impl->evts + i; // the aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)e->udata; tb_assert_and_check_return_val(aioo && aioo->sock, -1); // the sock tb_socket_ref_t sock = aioo->sock; // spak? if (sock == aiop->spak[1] && e->filter == EVFILT_READ) { // read spak tb_char_t spak = '\0'; if (1 != tb_socket_recv(aiop->spak[1], (tb_byte_t*)&spak, 1)) return -1; // killed? if (spak == 'k') return -1; // continue it continue ; } // skip spak tb_check_continue(sock != aiop->spak[1]); // init the aioe tb_aioe_ref_t aioe = &list[wait++]; aioe->code = TB_AIOE_CODE_NONE; aioe->aioo = (tb_aioo_ref_t)aioo; aioe->priv = aioo->priv; if (e->filter == EVFILT_READ) { aioe->code |= TB_AIOE_CODE_RECV; if (aioo->code & TB_AIOE_CODE_ACPT) aioe->code |= TB_AIOE_CODE_ACPT; } if (e->filter == EVFILT_WRITE) { aioe->code |= TB_AIOE_CODE_SEND; if (aioo->code & TB_AIOE_CODE_CONN) aioe->code |= TB_AIOE_CODE_CONN; } if ((e->flags & EV_ERROR) && !(aioe->code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND))) aioe->code |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND; // oneshot? clear it if (aioo->code & TB_AIOE_CODE_ONESHOT) { aioo->code = TB_AIOE_CODE_NONE; aioo->priv = tb_null; } } // ok return wait; }
static tb_void_t tb_ifaddrs_interface_done_hwaddr(tb_list_ref_t interfaces, tb_hash_map_ref_t names, struct nlmsghdr* response) { // check tb_assert_and_check_return(interfaces && names && response); // the info struct ifaddrmsg* info = (struct ifaddrmsg *)NLMSG_DATA(response); // attempt to find the interface name tb_bool_t owner = tb_false; tb_char_t* name = (tb_char_t*)tb_hash_map_get(names, tb_u2p(info->ifa_index)); if (!name) { // get the interface name struct rtattr* rta = tb_null; tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg)); for(rta = IFLA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size)) { // done tb_pointer_t rta_data = RTA_DATA(rta); tb_size_t rta_data_size = RTA_PAYLOAD(rta); switch(rta->rta_type) { case IFLA_IFNAME: { // make name name = (tb_char_t*)tb_ralloc(name, rta_data_size + 1); tb_assert_and_check_break(name); // copy name tb_strlcpy(name, rta_data, rta_data_size + 1); // save name tb_hash_map_insert(names, tb_u2p(info->ifa_index), name); owner = tb_true; } break; default: break; } } } // check tb_check_return(name); // done struct rtattr* rta = tb_null; tb_size_t rta_size = NLMSG_PAYLOAD(response, sizeof(struct ifaddrmsg)); for(rta = IFLA_RTA(info); RTA_OK(rta, rta_size); rta = RTA_NEXT(rta, rta_size)) { /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, name); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // done tb_pointer_t rta_data = RTA_DATA(rta); tb_size_t rta_data_size = RTA_PAYLOAD(rta); switch(rta->rta_type) { case IFLA_ADDRESS: { // no hwaddr? if (!(interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR)) { // check tb_check_break(rta_data_size == sizeof(interface->hwaddr.u8)); // save flags interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; if (info->ifa_flags & IFF_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; // save hwaddr tb_memcpy(interface->hwaddr.u8, rta_data, sizeof(interface->hwaddr.u8)); // trace tb_trace_d("name: %s, hwaddr: %{hwaddr}", name, &interface->hwaddr); // new interface? save it if (interface == &interface_new) { // save interface name interface->name = tb_strdup(name); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } } } break; case IFLA_IFNAME: case IFLA_BROADCAST: case IFLA_STATS: break; default: break; } } // exit name if (name && owner) tb_free(name); name = tb_null; }
static tb_void_t tb_ifaddrs_interface_load4(tb_list_ref_t interfaces) { // check tb_assert_and_check_return(interfaces); // done PIP_ADAPTER_INFO adapter_info = tb_null; do { // make the adapter info adapter_info = tb_malloc0_type(IP_ADAPTER_INFO); tb_assert_and_check_break(adapter_info); // get the real adapter info size ULONG size = sizeof(IP_ADAPTER_INFO); if (tb_iphlpapi()->GetAdaptersInfo(adapter_info, &size) == ERROR_BUFFER_OVERFLOW) { // grow the adapter info buffer adapter_info = (PIP_ADAPTER_INFO)tb_ralloc(adapter_info, size); tb_assert_and_check_break(adapter_info); // reclear it tb_memset(adapter_info, 0, size); } // get the adapter info if (tb_iphlpapi()->GetAdaptersInfo(adapter_info, &size) != NO_ERROR) break; // done PIP_ADAPTER_INFO adapter = adapter_info; while (adapter) { // check tb_assert(adapter->AdapterName); /* attempt to get the interface from the cached interfaces * and make a new interface if no the cached interface */ tb_ifaddrs_interface_t interface_new = {0}; tb_ifaddrs_interface_ref_t interface = tb_ifaddrs_interface_find((tb_iterator_ref_t)interfaces, adapter->AdapterName); if (!interface) interface = &interface_new; // check tb_assert(interface == &interface_new || interface->name); // save flags if (adapter->Type == MIB_IF_TYPE_LOOPBACK) interface->flags |= TB_IFADDRS_INTERFACE_FLAG_IS_LOOPBACK; // save hwaddr if (adapter->AddressLength == sizeof(interface->hwaddr.u8)) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_HWADDR; tb_memcpy(interface->hwaddr.u8, adapter->Address, sizeof(interface->hwaddr.u8)); } // save ipaddrs PIP_ADDR_STRING ipAddress = &adapter->IpAddressList; while (ipAddress && (interface->flags & TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) != TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR) { // done tb_ipaddr_t ipaddr; if ( ipAddress->IpAddress.String && tb_ipaddr_ip_cstr_set(&ipaddr, ipAddress->IpAddress.String, TB_IPADDR_FAMILY_NONE)) { if (ipaddr.family == TB_IPADDR_FAMILY_IPV4) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR4; interface->ipaddr4 = ipaddr.u.ipv4; } else if (ipaddr.family == TB_IPADDR_FAMILY_IPV6) { interface->flags |= TB_IFADDRS_INTERFACE_FLAG_HAVE_IPADDR6; interface->ipaddr6 = ipaddr.u.ipv6; } } // the next ipAddress = ipAddress->Next; } // new interface? save it if ( interface == &interface_new && interface->flags) { // save interface name interface->name = tb_strdup(adapter->AdapterName); tb_assert(interface->name); // save interface tb_list_insert_tail(interfaces, interface); } // the next adapter adapter = adapter->Next; } } while (0); // exit the adapter info if (adapter_info) tb_free(adapter_info); adapter_info = tb_null; }
static tb_static_large_data_head_t* tb_static_large_allocator_malloc_find(tb_static_large_allocator_ref_t allocator, tb_static_large_data_head_t* data_head, tb_size_t walk_size, tb_size_t space) { // check tb_assert_and_check_return_val(allocator && data_head && space, tb_null); // the data tail tb_static_large_data_head_t* data_tail = allocator->data_tail; tb_check_return_val(data_head < data_tail, tb_null); // find the free data while ((data_head + 1) <= data_tail && walk_size) { // the data space size tb_size_t data_space = data_head->space; // check the space size tb_assert(!((sizeof(tb_static_large_data_head_t) + data_space) & (allocator->page_size - 1))); #ifdef __tb_debug__ // check the data if (!data_head->bfree) tb_static_large_allocator_check_data(allocator, data_head); #endif // allocate if the data is free if (data_head->bfree) { // is enough? if (data_space >= space) { // remove this free data from the pred cache tb_static_large_allocator_pred_remove(allocator, data_head); // split it if this free data is too large if (data_space > sizeof(tb_static_large_data_head_t) + space) { // split this free data tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + space); next_head->space = data_space - space - sizeof(tb_static_large_data_head_t); next_head->bfree = 1; data_head->space = space; // add next free data to the pred cache tb_static_large_allocator_pred_update(allocator, next_head); } else { // the next data head tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space); // the next data is free? if (next_head + 1 < data_tail && next_head->bfree) { // add next free data to the pred cache tb_static_large_allocator_pred_update(allocator, next_head); } } // allocate the data data_head->bfree = 0; // return the data head return data_head; } else // attempt to merge next free data if this free data is too small { // the next data head tb_static_large_data_head_t* next_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space); // break if doesn't exist next data tb_check_break(next_head + 1 < data_tail); // the next data is free? if (next_head->bfree) { // remove next free data from the pred cache tb_static_large_allocator_pred_remove(allocator, next_head); // remove this free data from the pred cache tb_static_large_allocator_pred_remove(allocator, data_head); // trace tb_trace_d("malloc: find: merge: %lu", next_head->space); // merge next data data_head->space += sizeof(tb_static_large_data_head_t) + next_head->space; // add this free data to the pred cache tb_static_large_allocator_pred_update(allocator, data_head); // continue handle this data continue ; } } } // walk_size-- walk_size--; // skip it if the data is non-free or too small data_head = (tb_static_large_data_head_t*)((tb_byte_t*)(data_head + 1) + data_space); } // failed return tb_null; }