static tb_size_t tb_vector_nremove_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_hong_t t = tb_mclock(); tb_vector_nremove(vector, tb_iterator_head(vector), n); t = tb_mclock() - t; // time tb_trace_i("tb_vector_nremove(%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); }
tb_pointer_t tb_heap_top(tb_heap_ref_t heap) { return tb_iterator_item(heap, tb_iterator_head(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_pointer_t tb_circle_queue_head(tb_circle_queue_ref_t self) { // the head item return tb_iterator_item((tb_iterator_ref_t)self, tb_iterator_head((tb_iterator_ref_t)self)); }
static __tb_inline__ tb_void_t g2_gl_draw_stencil_clip_path(g2_gl_draw_t* draw, g2_clipper_item_t const* item) { // check tb_assert_and_check_return(item->type == G2_CLIPPER_ITEM_PATH); // the clip path g2_gl_path_t* path = (g2_gl_path_t*)item->u.path; tb_assert_and_check_return(path); // null? tb_check_return(!g2_path_null(path)); // like g2_gl_path_make_like(path); // like rect? if (path->like == G2_GL_PATH_LIKE_RECT) { // clip bounds g2_gl_draw_stencil_clip_bounds(draw, &path->rect); // ok return ; } // like triangle? else if (path->like == G2_GL_PATH_LIKE_TRIG) { // clip triangle g2_clipper_item_t clip = {0}; clip.type = G2_CLIPPER_ITEM_TRIANGLE; clip.mode = item->mode; clip.u.triangle = path->trig; g2_gl_draw_stencil_clip_triangle(draw, &clip); // ok return ; } // make draw if (!g2_gl_path_make_fill(path)) return ; // check tb_assert(path->fill.data && tb_vector_size(path->fill.data)); tb_assert(path->fill.size && tb_vector_size(path->fill.size)); tb_check_return(path->fill.rect.x1 < path->fill.rect.x2 && path->fill.rect.y1 < path->fill.rect.y2); // init vertices if (draw->context->version < 0x20) g2_glVertexPointer(2, G2_GL_FLOAT, 0, tb_vector_data(path->fill.data)); else g2_glVertexAttribPointer(g2_gl_program_location(draw->program, G2_GL_PROGRAM_LOCATION_VERTICES), 2, G2_GL_FLOAT, G2_GL_FALSE, 0, tb_vector_data(path->fill.data)); // clip path tb_size_t head = 0; tb_size_t size = 0; tb_size_t itor = tb_iterator_head(path->fill.size); tb_size_t tail = tb_iterator_tail(path->fill.size); for (; itor != tail; itor++) { size = tb_iterator_item(path->fill.size, itor); g2_glDrawArrays(G2_GL_TRIANGLE_FAN, (g2_GLint_t)head, (g2_GLint_t)size); head += size; } }
tb_void_t tb_list_moveto_head(tb_list_ref_t self, tb_size_t move) { tb_list_moveto_prev(self, tb_iterator_head(self), move); }
tb_void_t tb_list_replace_head(tb_list_ref_t self, tb_cpointer_t data) { tb_list_replace(self, tb_iterator_head(self), data); }
tb_void_t tb_list_remove_head(tb_list_ref_t self) { tb_list_remove(self, tb_iterator_head(self)); }
tb_size_t tb_list_insert_head(tb_list_ref_t self, tb_cpointer_t data) { return tb_list_insert_prev(self, tb_iterator_head(self), data); }
tb_pointer_t tb_list_head(tb_list_ref_t self) { return tb_iterator_item(self, tb_iterator_head(self)); }
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); }
tb_pointer_t tb_vector_head(tb_vector_ref_t vector) { return tb_iterator_item(vector, tb_iterator_head(vector)); }
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_sort_all(tb_iterator_ref_t iterator, tb_iterator_comp_t comp) { tb_sort(iterator, tb_iterator_head(iterator), tb_iterator_tail(iterator), comp); }
tb_void_t g2_gl_draw_path(g2_gl_painter_t* painter, tb_size_t mode, g2_gl_path_t const* path) { // check tb_assert_and_check_return(painter && path); tb_assert_and_check_return((mode == G2_STYLE_MODE_FILL) || (mode == G2_STYLE_MODE_STOK)); // null? tb_check_return(!g2_path_null(path)); // make like g2_gl_path_make_like((g2_gl_path_t*)path); // make draw if (!g2_gl_path_make_fill((g2_gl_path_t*)path)) return ; // check tb_assert(path->fill.data && tb_vector_size(path->fill.data)); tb_assert(path->fill.size && tb_vector_size(path->fill.size)); tb_check_return(path->fill.rect.x1 < path->fill.rect.x2 && path->fill.rect.y1 < path->fill.rect.y2); // like rect? if (path->like == G2_GL_PATH_LIKE_RECT) { // draw bounds g2_gl_draw_bounds(painter, mode, &path->rect); // ok return ; } // like triangle? else if (path->like == G2_GL_PATH_LIKE_TRIG) { // draw triangle g2_gl_draw_triangle(painter, mode, &path->trig); // ok return ; } // init draw g2_gl_draw_t draw = {0}; if (!g2_gl_draw_init(&draw, painter, mode, path->like == G2_GL_PATH_LIKE_CONX? G2_GL_DRAW_FLAG_CONVEX : G2_GL_DRAW_FLAG_NONE)) return ; // init bounds g2_gl_rect_t bounds = path->fill.rect; if (draw.mode == G2_STYLE_MODE_STOK) g2_gl_bounds_stok(&bounds, 1); // clip draw g2_gl_draw_clip(&draw, &bounds); // init vertices if (draw.context->version < 0x20) g2_glVertexPointer(2, G2_GL_FLOAT, 0, tb_vector_data(path->fill.data)); else g2_glVertexAttribPointer(g2_gl_program_location(draw.program, G2_GL_PROGRAM_LOCATION_VERTICES), 2, G2_GL_FLOAT, G2_GL_FALSE, 0, tb_vector_data(path->fill.data)); // draw vertices tb_size_t head = 0; tb_size_t size = 0; tb_size_t itor = tb_iterator_head(path->fill.size); tb_size_t tail = tb_iterator_tail(path->fill.size); g2_GLenum_t gmode = (draw.mode == G2_STYLE_MODE_FILL)? G2_GL_TRIANGLE_FAN : G2_GL_LINE_STRIP; for (; itor != tail; itor++) { size = tb_iterator_item(path->fill.size, itor); g2_glDrawArrays(gmode, (g2_GLint_t)head, (g2_GLint_t)size); head += size; } // draw fill g2_gl_draw_fill(&draw, &bounds); // exit draw g2_gl_draw_exit(&draw); }