Beispiel #1
0
static tb_size_t tb_vector_nreplace_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_size_t n = 10000;
    tb_vector_ninsert_head(vector, (tb_pointer_t)0xf, n);
    tb_hong_t t = tb_mclock();
    tb_vector_nreplace_last(vector, (tb_pointer_t)0xd, n);
    t = tb_mclock() - t;

    // time
    tb_trace_i("tb_vector_nreplace_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) == n);
    tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xd);
    tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xd);


    // exit
    tb_vector_exit(vector);

    return n / ((tb_uint32_t)(t) + 1);
}
Beispiel #2
0
static tb_size_t tb_vector_insert_tail_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_hong_t t = tb_mclock();
    for (i = 0; i < n; i++) tb_vector_insert_tail(vector, (tb_pointer_t)0xf);
    t = tb_mclock() - t;

    // time
    tb_trace_i("tb_vector_insert_tail(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));

    // check
    tb_assert(tb_vector_size(vector) == n);
    tb_assert(tb_vector_head(vector) == (tb_pointer_t)0xf);
    tb_assert(tb_vector_last(vector) == (tb_pointer_t)0xf);

    // clear it
    tb_vector_clear(vector);
    tb_assert(!tb_vector_size(vector));

    // exit
    tb_vector_exit(vector);

    return n / ((tb_uint32_t)(t) + 1);
}
Beispiel #3
0
static tb_void_t tb_vector_int_dump(tb_vector_ref_t vector)
{
    tb_trace_i("tb_int_t size: %lu, maxn: %lu", tb_vector_size(vector), tb_vector_maxn(vector));
    tb_for_all (tb_char_t*, item, vector)
    {
        tb_trace_i("tb_int_t at[%lu]: %x", item_itor, item);
    }
Beispiel #4
0
tb_char_t const* tb_environment_at(tb_environment_ref_t environment, tb_size_t index)
{
    // check
    tb_assert_and_check_return_val(environment, tb_null);

    // get the value
    return (index < tb_vector_size(environment))? (tb_char_t const*)tb_iterator_item(environment, index) : tb_null;
}
Beispiel #5
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_size_t tb_environment_load(tb_environment_ref_t environment, tb_char_t const* name)
{
    // check
    tb_assert_and_check_return_val(environment && name, 0);

    // clear environment first
    tb_vector_clear(environment);

    // get values
    tb_char_t const* values = tb_environment_get_impl(name, tb_null);
    tb_check_return_val(values, 0);

    // init value string
    tb_string_t value;
    if (tb_string_init(&value)) 
    {
        // done
        tb_char_t const*    p = values;
        tb_char_t           c = '\0';
        while (1)
        {
            // the character
            c = *p++;

            // make value
            if (c != ';' && c) tb_string_chrcat(&value, c);
            else 
            {
                // save value to environment
                if (tb_string_size(&value)) 
                    tb_vector_insert_tail(environment, tb_string_cstr(&value));

                // clear value 
                tb_string_clear(&value);

                // end?
                tb_check_break(c);
            }
        }

        // exit value string
        tb_string_exit(&value);
    }

    // exit values
    if (values) tb_free(values);
    values = tb_null;

    // ok?
    return tb_vector_size(environment);
}
Beispiel #6
0
static tb_void_t tb_aiop_spak_klist(tb_aiop_ptor_impl_t* impl)
{
    // check
    tb_assert_and_check_return(impl && impl->klist);

    // enter
    tb_spinlock_enter(&impl->klock);

    // kill it if exists the killing aico
    if (tb_vector_size(impl->klist))
    {
        // kill all
        tb_for_all_if (tb_aico_impl_t*, aico, impl->klist, aico)
        {
            // the aiop aico
            tb_aiop_aico_t* aiop_aico = (tb_aiop_aico_t*)aico;

            // sock?
            if (aico->type == TB_AICO_TYPE_SOCK)
            {
                // add it first if do not exists timeout task
                if (!aiop_aico->task)
                {
                    aiop_aico->task = tb_ltimer_task_init(impl->ltimer, 10000, tb_false, tb_aiop_spak_wait_timeout, aico);
                    aiop_aico->bltimer = 1;
                }

                // kill the task
                if (aiop_aico->task)
                {
                    // kill task
                    if (aiop_aico->bltimer) tb_ltimer_task_kill(impl->ltimer, aiop_aico->task);
                    else tb_timer_task_kill(impl->timer, aiop_aico->task);
                }
            }
            else if (aico->type == TB_AICO_TYPE_FILE)
            {
                // kill file
                tb_aicp_file_kilo(impl, aico);
            }

            // trace
            tb_trace_d("kill: aico: %p, type: %u: ok", aico, aico->type);
        }
    }
Beispiel #7
0
static tb_size_t tb_vector_iterator_prev_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_rfor_all (tb_char_t*, item, vector) tb_used(item);
    t = tb_mclock() - t;

    // time
    tb_trace_i("tb_vector_iterator_prev(%lu): %lld ms, size: %lu, maxn: %lu", n, t, tb_vector_size(vector), tb_vector_maxn(vector));

    // exit
    tb_vector_exit(vector);

    return n / ((tb_uint32_t)(t) + 1);
}
Beispiel #8
0
tb_bool_t tb_environment_save(tb_environment_ref_t environment, tb_char_t const* name)
{
    // check
    tb_assert_and_check_return_val(environment && name, tb_false);

    // empty? remove this environment variable
    if (!tb_vector_size(environment)) return !unsetenv(name);

    // init values string
    tb_string_t values;
    if (!tb_string_init(&values)) return tb_false;

    // make values string
    tb_for_all_if (tb_char_t const*, value, environment, value)
    {
        // the single value cannot exist ':'
        tb_assertf(!tb_strchr(value, ':'), "invalid value: %s", value);

        // append value
        tb_string_cstrcat(&values, value);
        tb_string_chrcat(&values, ':');
    }
Beispiel #9
0
tb_void_t tb_vector_dump(tb_vector_ref_t vector)
{
    // check
    tb_vector_impl_t* impl = (tb_vector_impl_t*)vector;
    tb_assert_and_check_return(impl);

    // trace
    tb_trace_i("vector: size: %lu", tb_vector_size(vector));

    // done
    tb_char_t cstr[4096];
    tb_for_all (tb_pointer_t, data, vector)
    {
        // trace
        if (impl->element.cstr) 
        {
            tb_trace_i("    %s", impl->element.cstr(&impl->element, data, cstr, sizeof(cstr)));
        }
        else
        {
            tb_trace_i("    %p", data);
        }
    }
}
Beispiel #10
0
tb_size_t tb_environment_size(tb_environment_ref_t environment)
{
    return tb_vector_size(environment);
}
Beispiel #11
0
static tb_object_ref_t tb_object_bin_reader_func_dictionary(tb_object_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);

    // empty?
    if (!size) return tb_object_dictionary_init(TB_OBJECT_DICTIONARY_SIZE_MICRO, tb_false);

    // init dictionary
    tb_object_ref_t dictionary = tb_object_dictionary_init(0, tb_false);
    tb_assert_and_check_return_val(dictionary, tb_null);

    // walk
    tb_size_t       i = 0;
    tb_size_t       n = (tb_size_t)size;
    for (i = 0; i < n; i++)
    {
        // read key
        tb_object_ref_t key = tb_null;
        do
        {
            // the type & size
            tb_size_t               type = 0;
            tb_uint64_t             size = 0;
            tb_object_reader_bin_type_size(reader->stream, &type, &size);

            // trace
            tb_trace_d("key: type: %lu, size: %llu", type, size);

            // is index?
            if (!type)
            {
                // the object index
                tb_size_t index = (tb_size_t)size;
            
                // check
                tb_assert_and_check_break(index < tb_vector_size(reader->list));

                // the item
                key = (tb_object_ref_t)tb_iterator_item(reader->list, index);
            }
            else
            {
                // check
                tb_assert_and_check_break(type == TB_OBJECT_TYPE_STRING);

                // the reader func
                tb_object_bin_reader_func_t func = tb_object_bin_reader_func(type);
                tb_assert_and_check_break(func);

                // read it
                key = func(reader, type, size);
                tb_assert_and_check_break(key);

                // save it
                tb_vector_insert_tail(reader->list, key);

                // refn--
                tb_object_dec(key);
            }

        } while (0);

        // check
        tb_assert_and_check_break(key && tb_object_type(key) == TB_OBJECT_TYPE_STRING);
        tb_assert_and_check_break(tb_object_string_size(key) && tb_object_string_cstr(key));
        
        // read val
        tb_object_ref_t val = tb_null;
        do
        {
            // the type & size
            tb_size_t               type = 0;
            tb_uint64_t             size = 0;
            tb_object_reader_bin_type_size(reader->stream, &type, &size);

            // trace
            tb_trace_d("val: type: %lu, size: %llu", type, size);

            // is index?
            if (!type)
            {
                // the object index
                tb_size_t index = (tb_size_t)size;
            
                // check
                tb_assert_and_check_break(index < tb_vector_size(reader->list));

                // the item
                val = (tb_object_ref_t)tb_iterator_item(reader->list, index);

                // refn++
                if (val) tb_object_inc(val);
            }
            else
            {
                // the reader func
                tb_object_bin_reader_func_t func = tb_object_bin_reader_func(type);
                tb_assert_and_check_break(func);

                // read it
                val = func(reader, type, size);

                // save it
                if (val) tb_vector_insert_tail(reader->list, val);
            }
        
        } while (0);

        // check
        tb_assert_and_check_break(val);

        // set key => val
        tb_object_dictionary_set(dictionary, tb_object_string_cstr(key), val);
    }

    // failed?
    if (i != n)
    {
        if (dictionary) tb_object_exit(dictionary);
        dictionary = tb_null;
    }

    // ok?
    return dictionary;
}
Beispiel #12
0
static tb_object_ref_t tb_object_bin_reader_func_array(tb_object_bin_reader_t* reader, tb_size_t type, tb_uint64_t size)
{
    // check
    tb_assert_and_check_return_val(reader && reader->stream && reader->list, tb_null);

    // empty?
    if (!size) return tb_object_array_init(TB_OBJECT_BIN_READER_ARRAY_GROW, tb_false);

    // init array
    tb_object_ref_t array = tb_object_array_init(TB_OBJECT_BIN_READER_ARRAY_GROW, tb_false);
    tb_assert_and_check_return_val(array, tb_null);

    // walk
    tb_size_t i = 0;
    tb_size_t n = (tb_size_t)size;
    for (i = 0; i < n; i++)
    {
        // the type & size
        tb_size_t               type = 0;
        tb_uint64_t             size = 0;
        tb_object_reader_bin_type_size(reader->stream, &type, &size);

        // trace
        tb_trace_d("item: type: %lu, size: %llu", type, size);

        // is index?
        tb_object_ref_t item = tb_null;
        if (!type)
        {
            // the object index
            tb_size_t index = (tb_size_t)size;
        
            // check
            tb_assert_and_check_break(index < tb_vector_size(reader->list));

            // the item
            item = (tb_object_ref_t)tb_iterator_item(reader->list, index);

            // refn++
            if (item) tb_object_inc(item);
        }
        else
        {
            // the reader func
            tb_object_bin_reader_func_t func = tb_object_bin_reader_func(type);
            tb_assert_and_check_break(func);

            // read it
            item = func(reader, type, size);

            // save it
            tb_vector_insert_tail(reader->list, item);
        }

        // check
        tb_assert_and_check_break(item);

        // append item
        tb_object_array_append(array, item);
    }

    // failed?
    if (i != n)
    {
        if (array) tb_object_exit(array);
        array = tb_null;
    }

    // ok?
    return array;
}
Beispiel #13
0
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;
	}
}
Beispiel #14
0
tb_void_t tb_vector_ninsert_tail(tb_vector_ref_t vector, tb_cpointer_t data, tb_size_t size)
{
    tb_vector_ninsert_prev(vector, tb_vector_size(vector), data, size);
}
Beispiel #15
0
tb_size_t tb_stack_size(tb_stack_ref_t stack)
{
    return tb_vector_size((tb_vector_ref_t)stack);
}
Beispiel #16
0
static tb_long_t tb_aiop_rtor_poll_wait(tb_aiop_rtor_impl_t* rtor, tb_aioe_t* list, tb_size_t maxn, tb_long_t timeout)
{   
    // check
    tb_aiop_rtor_poll_impl_t* impl = (tb_aiop_rtor_poll_impl_t*)rtor;
    tb_assert_and_check_return_val(impl && impl->pfds && impl->cfds && list && maxn, -1);

    // the aiop
    tb_aiop_impl_t* aiop = rtor->aiop;
    tb_assert_and_check_return_val(aiop, tb_false);

    // 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))
    {
        // copy pfds
        tb_spinlock_enter(&impl->lock.pfds);
        tb_vector_copy(impl->cfds, impl->pfds);
        tb_spinlock_leave(&impl->lock.pfds);

        // cfds
        struct pollfd*  cfds = (struct pollfd*)tb_vector_data(impl->cfds);
        tb_size_t       cfdm = tb_vector_size(impl->cfds);
        tb_assert_and_check_return_val(cfds && cfdm, -1);

        // wait
        tb_long_t cfdn = poll(cfds, cfdm, timeout);
        tb_assert_and_check_return_val(cfdn >= 0, -1);

        // timeout?
        tb_check_return_val(cfdn, 0);

        // sync
        tb_size_t i = 0;
        for (i = 0; i < cfdm && wait < maxn; i++)
        {
            // the sock
            tb_socket_ref_t sock = tb_fd2sock(cfds[i].fd);
            tb_assert_and_check_return_val(sock, -1);

            // the events
            tb_size_t events = cfds[i].revents;
            tb_check_continue(events);

            // spak?
            if (sock == aiop->spak[1] && (events & POLLIN))
            {
                // 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;

                // stop to wait
                stop = tb_true;

                // continue it
                continue ;
            }

            // skip spak
            tb_check_continue(sock != aiop->spak[1]);

            // the aioo
            tb_size_t       code = TB_AIOE_CODE_NONE;
            tb_cpointer_t   priv = tb_null;
            tb_aioo_impl_t*      aioo = tb_null;
            tb_spinlock_enter(&impl->lock.hash);
            if (impl->hash)
            {
                aioo = (tb_aioo_impl_t*)tb_hash_get(impl->hash, sock);
                if (aioo) 
                {
                    // save code & data
                    code = aioo->code;
                    priv = aioo->priv;

                    // oneshot? clear it
                    if (aioo->code & TB_AIOE_CODE_ONESHOT)
                    {
                        aioo->code = TB_AIOE_CODE_NONE;
                        aioo->priv = tb_null;
                    }
                }
            }
            tb_spinlock_leave(&impl->lock.hash);
            tb_check_continue(aioo && code);
            
            // init aioe
            tb_aioe_t   aioe = {0};
            aioe.priv   = priv;
            aioe.aioo   = (tb_aioo_ref_t)aioo;
            if (events & POLLIN)
            {
                aioe.code |= TB_AIOE_CODE_RECV;
                if (code & TB_AIOE_CODE_ACPT) aioe.code |= TB_AIOE_CODE_ACPT;
            }
            if (events & POLLOUT) 
            {
                aioe.code |= TB_AIOE_CODE_SEND;
                if (code & TB_AIOE_CODE_CONN) aioe.code |= TB_AIOE_CODE_CONN;
            }
            if ((events & POLLHUP) && !(code & (TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND))) 
                aioe.code |= TB_AIOE_CODE_RECV | TB_AIOE_CODE_SEND;

            // save aioe
            list[wait++] = aioe;

            // oneshot?
            if (code & TB_AIOE_CODE_ONESHOT)
            {
                tb_spinlock_enter(&impl->lock.pfds);
                struct pollfd* pfds = (struct pollfd*)tb_vector_data(impl->pfds);
                if (pfds) pfds[i].events = 0;
                tb_spinlock_leave(&impl->lock.pfds);
            }
        }
    }

    // ok
    return wait;
}
Beispiel #17
0
tb_long_t tb_poller_wait(tb_poller_ref_t self, tb_poller_event_func_t func, tb_long_t timeout)
{
    // check
    tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
    tb_assert_and_check_return_val(poller && poller->pfds && poller->cfds && func, -1);

    // 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))
    {
        // pfds
        struct pollfd*  pfds = (struct pollfd*)tb_vector_data(poller->pfds);
        tb_size_t       pfdm = tb_vector_size(poller->pfds);
        tb_assert_and_check_return_val(pfds && pfdm, -1);

        // wait
        tb_long_t pfdn = poll(pfds, pfdm, timeout);
        tb_assert_and_check_return_val(pfdn >= 0, -1);

        // timeout?
        tb_check_return_val(pfdn, 0);

        // copy fds
        tb_vector_copy(poller->cfds, poller->pfds);

        // walk the copied fds
        pfds = (struct pollfd*)tb_vector_data(poller->cfds);
        pfdm = tb_vector_size(poller->cfds);

        // sync
        tb_size_t i = 0;
        for (i = 0; i < pfdm; i++)
        {
            // the sock
            tb_socket_ref_t sock = tb_fd2sock(pfds[i].fd);
            tb_assert_and_check_return_val(sock, -1);

            // the poll events
            tb_size_t poll_events = pfds[i].revents;
            tb_check_continue(poll_events);

            // spak?
            if (sock == poller->pair[1] && (poll_events & POLLIN))
            {
                // read spak
                tb_char_t spak = '\0';
                if (1 != tb_socket_recv(poller->pair[1], (tb_byte_t*)&spak, 1)) return -1;

                // killed?
                if (spak == 'k') return -1;

                // stop to wait
                stop = tb_true;

                // continue it
                continue ;
            }

            // skip spak
            tb_check_continue(sock != poller->pair[1]);

            // init events
            tb_size_t events = TB_POLLER_EVENT_NONE;
            if (poll_events & POLLIN) events |= TB_POLLER_EVENT_RECV;
            if (poll_events & POLLOUT) events |= TB_POLLER_EVENT_SEND;
            if ((poll_events & POLLHUP) && !(events & (TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND))) 
                events |= TB_POLLER_EVENT_RECV | TB_POLLER_EVENT_SEND;

            // call event function
            func(self, sock, events, tb_poller_hash_get(poller, sock));

            // update the events count
            wait++;
        }
    }

    // ok
    return wait;
}
Beispiel #18
0
tb_void_t tb_vector_insert_tail(tb_vector_ref_t vector, tb_cpointer_t data)
{
    tb_vector_insert_prev(vector, tb_vector_size(vector), data);
}
Beispiel #19
0
static tb_pointer_t tb_thread_pool_worker_loop(tb_cpointer_t priv)
{
    // the worker
    tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)priv;

    // trace
    tb_trace_d("worker[%lu]: init", worker? worker->id : -1);

    // done
    do
    {
        // check
        tb_assert_and_check_break(worker && !worker->jobs && !worker->stats);

        // the pool
        tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool;
        tb_assert_and_check_break(impl && impl->semaphore);

        // wait some time for leaving the lock
        tb_msleep((worker->id + 1)* 20);

        // init jobs
        worker->jobs = tb_vector_init(TB_THREAD_POOL_JOBS_WORKING_GROW, tb_element_ptr(tb_null, tb_null));
        tb_assert_and_check_break(worker->jobs);

        // init stats
        worker->stats = tb_hash_map_init(TB_HASH_MAP_BUCKET_SIZE_MICRO, tb_element_ptr(tb_null, tb_null), tb_element_mem(sizeof(tb_thread_pool_job_stats_t), tb_null, tb_null));
        tb_assert_and_check_break(worker->stats);
        
        // loop
        while (1)
        {
            // pull jobs if be idle
            if (!tb_vector_size(worker->jobs))
            {
                // enter 
                tb_spinlock_enter(&impl->lock);

                // init the pull time
                worker->pull = 0;

                // pull from the urgent jobs
                if (tb_list_entry_size(&impl->jobs_urgent))
                {
                    // trace
                    tb_trace_d("worker[%lu]: try pulling from urgent: %lu", worker->id, tb_list_entry_size(&impl->jobs_urgent));

                    // pull it
                    tb_remove_if_until(tb_list_entry_itor(&impl->jobs_urgent), tb_thread_pool_worker_walk_pull, worker);
                }

                // pull from the waiting jobs
                if (tb_list_entry_size(&impl->jobs_waiting))
                {
                    // trace
                    tb_trace_d("worker[%lu]: try pulling from waiting: %lu", worker->id, tb_list_entry_size(&impl->jobs_waiting));

                    // pull it
                    tb_remove_if_until(tb_list_entry_itor(&impl->jobs_waiting), tb_thread_pool_worker_walk_pull, worker);
                }

                // pull from the pending jobs and clean some finished and killed jobs
                if (tb_list_entry_size(&impl->jobs_pending))
                {
                    // trace
                    tb_trace_d("worker[%lu]: try pulling from pending: %lu", worker->id, tb_list_entry_size(&impl->jobs_pending));

                    // no jobs? try to pull from the pending jobs
                    if (!tb_vector_size(worker->jobs))
                        tb_remove_if(tb_list_entry_itor(&impl->jobs_pending), tb_thread_pool_worker_walk_pull_and_clean, worker);
                    // clean some finished and killed jobs
                    else tb_remove_if(tb_list_entry_itor(&impl->jobs_pending), tb_thread_pool_worker_walk_clean, worker);
                }

                // leave 
                tb_spinlock_leave(&impl->lock);

                // idle? wait it
                if (!tb_vector_size(worker->jobs))
                {
                    // killed?
                    tb_check_break(!tb_atomic_get(&worker->bstoped));

                    // trace
                    tb_trace_d("worker[%lu]: wait: ..", worker->id);

                    // wait some time
                    tb_long_t wait = tb_semaphore_wait(impl->semaphore, -1);
                    tb_assert_and_check_break(wait > 0);

                    // trace
                    tb_trace_d("worker[%lu]: wait: ok", worker->id);

                    // continue it
                    continue;
                }
                else
                {
#ifdef TB_TRACE_DEBUG
                    // update the jobs urgent size
                    tb_size_t jobs_urgent_size = tb_list_entry_size(&impl->jobs_urgent);

                    // update the jobs waiting size
                    tb_size_t jobs_waiting_size = tb_list_entry_size(&impl->jobs_waiting);

                    // update the jobs pending size
                    tb_size_t jobs_pending_size = tb_list_entry_size(&impl->jobs_pending);

                    // trace
                    tb_trace_d("worker[%lu]: pull: jobs: %lu, time: %lu ms, waiting: %lu, pending: %lu, urgent: %lu", worker->id, tb_vector_size(worker->jobs), worker->pull, jobs_waiting_size, jobs_pending_size, jobs_urgent_size);
#endif
                }
            }

            // done jobs
            tb_for_all (tb_thread_pool_job_t*, job, worker->jobs)
            {
                // check
                tb_assert_and_check_continue(job && job->task.done);

                // the job state
                tb_size_t state = tb_atomic_fetch_and_pset(&job->state, TB_STATE_WAITING, TB_STATE_WORKING);
                
                // the job is waiting? work it
                if (state == TB_STATE_WAITING)
                {
                    // trace
                    tb_trace_d("worker[%lu]: done: task[%p:%s]: ..", worker->id, job->task.done, job->task.name);

                    // init the time
                    tb_hong_t time = tb_cache_time_spak();

                    // done the job
                    job->task.done((tb_thread_pool_worker_ref_t)worker, job->task.priv);

                    // computate the time
                    time = tb_cache_time_spak() - time;

                    // exists? update time and count
                    tb_size_t               itor;
                    tb_hash_map_item_ref_t  item = tb_null;
                    if (    ((itor = tb_hash_map_find(worker->stats, job->task.done)) != tb_iterator_tail(worker->stats))
                        &&  (item = (tb_hash_map_item_ref_t)tb_iterator_item(worker->stats, itor)))
                    {
                        // the stats
                        tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)item->data;
                        tb_assert_and_check_break(stats);

                        // update the done count
                        stats->done_count++;

                        // update the total time 
                        stats->total_time += time;
                    }
                    
                    // no item? add it
                    if (!item) 
                    {
                        // init stats
                        tb_thread_pool_job_stats_t stats = {0};
                        stats.done_count = 1;
                        stats.total_time = time;

                        // add stats
                        tb_hash_map_insert(worker->stats, job->task.done, &stats);
                    }

#ifdef TB_TRACE_DEBUG
                    tb_size_t done_count = 0;
                    tb_hize_t total_time = 0;
                    tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)tb_hash_map_get(worker->stats, job->task.done);
                    if (stats)
                    {
                        done_count = stats->done_count;
                        total_time = stats->total_time;
                    }

                    // trace
                    tb_trace_d("worker[%lu]: done: task[%p:%s]: time: %lld ms, average: %lld ms, count: %lu", worker->id, job->task.done, job->task.name, time, (total_time / (tb_hize_t)done_count), done_count);
#endif

                    // update the job state
                    tb_atomic_set(&job->state, TB_STATE_FINISHED);
                }
                // the job is killing? work it
                else if (state == TB_STATE_KILLING)
                {
                    // update the job state
                    tb_atomic_set(&job->state, TB_STATE_KILLED);
                }
            }

            // clear jobs
            tb_vector_clear(worker->jobs);
        }

    } while (0);

    // exit worker
    if (worker)
    {
        // trace
        tb_trace_d("worker[%lu]: exit", worker->id);

        // stoped
        tb_atomic_set(&worker->bstoped, 1);

        // exit all private data
        tb_size_t i = 0;
        tb_size_t n = tb_arrayn(worker->priv);
        for (i = 0; i < n; i++)
        {
            // the private data
            tb_thread_pool_worker_priv_t* priv = &worker->priv[n - i - 1];

            // exit it
            if (priv->exit) priv->exit((tb_thread_pool_worker_ref_t)worker, priv->priv);

            // clear it
            priv->exit = tb_null;
            priv->priv = tb_null;
        }

        // exit stats
        if (worker->stats) tb_hash_map_exit(worker->stats);
        worker->stats = tb_null;

        // exit jobs
        if (worker->jobs) tb_vector_exit(worker->jobs);
        worker->jobs = tb_null;
    }

    // exit
    tb_thread_return(tb_null);
    return tb_null;
}
Beispiel #20
0
tb_bool_t tb_vector_save(tb_vector_ref_t vector, tb_stream_ref_t stream)
{
    // check
    tb_vector_impl_t* impl = (tb_vector_impl_t*)vector;
    tb_assert_and_check_return_val(impl && stream, tb_false);
    tb_assert_and_check_return_val(impl->func.hash && impl->func.save, tb_false);
    
    // the offset
    tb_hize_t offset = tb_stream_offset(stream);

    // done
    tb_bool_t   ok = tb_false;
    tb_uint32_t crc32 = 0;
    do
    {
        // calc type
        crc32 = tb_crc_encode_cstr(TB_CRC_MODE_32_IEEE_LE, crc32, "vector");

        // calc item type
        crc32 = tb_crc_encode_value(TB_CRC_MODE_32_IEEE_LE, crc32, impl->func.type);

        // calc item size
        crc32 = tb_crc_encode_value(TB_CRC_MODE_32_IEEE_LE, crc32, impl->func.size);

        // save the head crc32
        if (!tb_stream_bwrit_u32_be(stream, crc32)) break;

        // the size
        tb_size_t size = tb_vector_size(vector);

        // save size
        if (!tb_stream_bwrit_u32_be(stream, (tb_uint32_t)size)) break;
        
        // save vector
        tb_size_t save = 0;
        tb_for_all (tb_cpointer_t, item, vector)
        {
            // save item
            if (!impl->func.save(&impl->func, item, stream)) break;

            // hash item
            tb_size_t hash = impl->func.hash(&impl->func, item, -1, 0);

            // calc item
            crc32 = tb_crc_encode_value(TB_CRC_MODE_32_IEEE_LE, crc32, hash);

            // update the save count
            save++;
        }

        // check
        tb_assert_and_check_break(save == size); 
 
        // save the body crc32
        if (!tb_stream_bwrit_u32_be(stream, crc32)) break;
        
        // ok
        ok = tb_true;

    } while (0);

    // failed? restore it
    if (!ok) tb_stream_seek(stream, offset);

    // ok?
    return ok;
}
Beispiel #21
0
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);
}