Esempio n. 1
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);
}
Esempio n. 2
0
tb_bool_t tb_environment_insert(tb_environment_ref_t environment, tb_char_t const* value, tb_bool_t to_head)
{
    // check
    tb_assert_and_check_return_val(environment && value, tb_false);

    // insert value into the head
    if (to_head) tb_vector_insert_head(environment, value);
    // insert value into the tail
    else tb_vector_insert_tail(environment, value);

    // ok
    return tb_true;
}
Esempio n. 3
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);
}
Esempio n. 4
0
tb_bool_t tb_environment_replace(tb_environment_ref_t environment, tb_char_t const* value)
{
    // check
    tb_assert_and_check_return_val(environment, tb_false);

    // clear it first
    tb_vector_clear(environment);

    // insert value
    if (value) tb_vector_insert_tail(environment, value);

    // ok
    return tb_true;
}
Esempio n. 5
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * worker implementation
 */
static tb_bool_t tb_thread_pool_worker_walk_pull(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value, tb_bool_t* is_break)
{
    // the worker pull
    tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)value;
    tb_assert_abort(worker && worker->jobs && worker->stats && is_break);

    // full?
    if (worker->pull >= TB_THREAD_POOL_JOBS_PULL_TIME_MAXN)
    {
        // break it
        *is_break = tb_true;
        return tb_false;
    }

    // the job
    tb_thread_pool_job_t* job = (tb_thread_pool_job_t*)item;
    tb_assert_abort(job);

    // the pool
    tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool;
    tb_assert_abort(impl);

    // append the job to the pending jobs
    tb_list_entry_insert_tail(&impl->jobs_pending, &job->entry);  

    // append the job to the working jobs
    tb_vector_insert_tail(worker->jobs, job);   

    // computate the job average time 
    tb_size_t average_time = 200;
    if (tb_hash_map_size(worker->stats))
    {
        tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)tb_hash_map_get(worker->stats, job->task.done);
        if (stats && stats->done_count) average_time = (tb_size_t)(stats->total_time / stats->done_count);
    }

    // update the pull time
    worker->pull += average_time;

    // trace
    tb_trace_d("worker[%lu]: pull: task[%p:%s] from %s", worker->id, job->task.done, job->task.name, iterator == tb_list_entry_itor(&impl->jobs_waiting)? "waiting" : "urgent");

    // remove the job from the waiting or urgent jobs
    return tb_true;
}
Esempio n. 6
0
static tb_bool_t tb_aiop_rtor_poll_addo(tb_aiop_rtor_impl_t* rtor, tb_aioo_impl_t const* aioo)
{
    // 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 && aioo && aioo->sock, tb_false);

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

    // add sock => aioo
    tb_bool_t ok = tb_false;
    tb_spinlock_enter(&impl->lock.hash);
    if (impl->hash) 
    {
        tb_hash_set(impl->hash, aioo->sock, aioo);
        ok = tb_true;
    }
    tb_spinlock_leave(&impl->lock.hash);
    tb_assert_and_check_return_val(ok, tb_false);

    // the code
    tb_size_t code = aioo->code;

    // init pfd
    struct pollfd pfd = {0};
    pfd.fd = ((tb_long_t)aioo->sock) - 1;
    if (code & TB_AIOE_CODE_RECV || code & TB_AIOE_CODE_ACPT) pfd.events |= POLLIN;
    if (code & TB_AIOE_CODE_SEND || code & TB_AIOE_CODE_CONN) pfd.events |= POLLOUT;

    // add pfd, TODO: addo by binary search
    tb_spinlock_enter(&impl->lock.pfds);
    tb_vector_insert_tail(impl->pfds, &pfd);
    tb_spinlock_leave(&impl->lock.pfds);

    // spak it
    if (aiop->spak[0] && code) tb_socket_send(aiop->spak[0], (tb_byte_t const*)"p", 1);

    // ok?
    return ok;
}
Esempio n. 7
0
tb_bool_t tb_poller_insert(tb_poller_ref_t self, tb_socket_ref_t sock, tb_size_t events, tb_cpointer_t priv)
{
    // check
    tb_poller_poll_ref_t poller = (tb_poller_poll_ref_t)self;
    tb_assert_and_check_return_val(poller && poller->pfds && sock, tb_false);

    // oneshot is not supported now
    tb_assertf(!(events & TB_POLLER_EVENT_ONESHOT), "cannot insert events with oneshot, not supported!");

    // init events
    struct pollfd pfd = {0};
    if (events & TB_POLLER_EVENT_RECV) pfd.events |= POLLIN;
    if (events & TB_POLLER_EVENT_SEND) pfd.events |= POLLOUT;

    // save fd, TODO uses binary search
    pfd.fd = tb_sock2fd(sock);
    tb_vector_insert_tail(poller->pfds, &pfd);

    // bind user private data to socket
    tb_poller_hash_set(poller, sock, priv);

    // ok
    return tb_true;
}
Esempio n. 8
0
File: pcre2.c Progetto: waruqi/tbox
tb_long_t tb_regex_match(tb_regex_ref_t self, tb_char_t const* cstr, tb_size_t size, tb_size_t start, tb_size_t* plength, tb_vector_ref_t* presults)
{
    // check
    tb_regex_t* regex = (tb_regex_t*)self;
    tb_assert_and_check_return_val(regex && regex->code && regex->match_data && cstr, -1);

    // done
    tb_long_t ok = -1;
    do
    {
        // clear length first
        if (plength) *plength = 0;

        // end?
        tb_check_break(start < size);

        // init options
#ifdef __tb_debug__
        tb_uint32_t options = 0;
#else
        tb_uint32_t options = PCRE2_NO_UTF_CHECK;
#endif

        // match it
        tb_long_t count = pcre2_match(regex->code, (PCRE2_SPTR)cstr, (PCRE2_SIZE)size, (PCRE2_SIZE)start, options, regex->match_data, tb_null);
        if (count < 0)
        {
            // no match?
            tb_check_break(count != PCRE2_ERROR_NOMATCH);

#if defined(__tb_debug__) && !defined(TB_CONFIG_OS_WINDOWS)
            // get error info
            PCRE2_UCHAR info[256];
            pcre2_get_error_message(count, info, sizeof(info));

            // trace
            tb_trace_d("match failed at offset %lu: error: %ld, %s\n", start, count, info);
#endif

            // end
            break;
        }

        // check
        tb_assertf_and_check_break(count, "ovector has not enough space!");

        // get output vector
        PCRE2_SIZE* ovector = pcre2_get_ovector_pointer(regex->match_data);
        tb_assert_and_check_break(ovector);

        // get the match offset and length
        tb_size_t offset = (tb_size_t)ovector[0];
        tb_size_t length = (tb_size_t)ovector[1] - ovector[0];
        tb_assert_and_check_break(offset + length <= size);

        // trace
        tb_trace_d("matched count: %lu, offset: %lu, length: %lu", count, offset, length);

        // save results
        if (presults)
        {
            // init results if not exists
            tb_vector_ref_t results = *presults;
            if (!results)
            {
                // init it
                if (!regex->results) regex->results = tb_vector_init(16, tb_element_mem(sizeof(tb_regex_match_t), tb_regex_match_exit, tb_null));

                // save it
                *presults = results = regex->results;
            }
            tb_assert_and_check_break(results);

            // clear it first
            tb_vector_clear(results);

            // done
            tb_long_t           i = 0;
            tb_regex_match_t    entry;
            for (i = 0; i < count; i++)
            {
                // get substring offset and length
                tb_size_t substr_offset = ovector[i << 1];
                tb_size_t substr_length = ovector[(i << 1) + 1] - ovector[i << 1];
                tb_assert_and_check_break(substr_offset + substr_length <= size);

                // make match entry
                entry.cstr  = tb_strndup(cstr + substr_offset, substr_length);
                entry.size  = substr_length;
                entry.start = substr_offset;
                tb_assert_and_check_break(entry.cstr);
                
                // trace
                tb_trace_d("    matched: [%lu, %lu]: %s", entry.start, entry.size, entry.cstr);

                // append it
                tb_vector_insert_tail(results, &entry);
            }
            tb_assert_and_check_break(i == count);
        }

        // save length 
        if (plength) *plength = length;

        // ok
        ok = offset;

    } while (0);

    // ok?
    return ok;
}
Esempio n. 9
0
tb_bool_t tb_vector_load(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.load && impl->func.free, tb_false);

    // clear the vector first
    tb_vector_clear(vector);
  
    // the offset
    tb_hize_t offset = tb_stream_offset(stream);

    // done
    tb_bool_t       ok = tb_false;
    tb_uint32_t     crc32 = 0;
    tb_pointer_t    buff = tb_null;
    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);

        // load the head crc32
        tb_uint32_t crc32_head = tb_stream_bread_u32_be(stream);
        tb_assert_and_check_break(crc32_head == crc32);

        // make item buffer
        buff = impl->func.size? tb_malloc(impl->func.size) : tb_null;

        // load size
        tb_uint32_t size = tb_stream_bread_u32_be(stream);

        // load vector
        tb_uint32_t load = 0;
        for (load = 0; load < size; load++)
        {
            // load item
            if (!impl->func.load(&impl->func, buff, stream)) break;

            // the item data
            tb_cpointer_t data = impl->func.data(&impl->func, buff);

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

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

            // save item
            tb_vector_insert_tail(vector, data);

            // free name
            impl->func.free(&impl->func, buff);
        }

        // check
        tb_assert_and_check_break(load == size);

        // load the body crc32
        tb_uint32_t crc32_body = tb_stream_bread_u32_be(stream);
        tb_assert_and_check_break(crc32_body == crc32);

        // ok
        ok = tb_true;

    } while (0);

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

        // clear it
        tb_vector_clear(vector);
    }

    // exit buffer
    if (buff) tb_free(buff);
    buff = tb_null;

    // ok?
    return ok;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
static tb_bool_t tb_thread_pool_worker_walk_pull_and_clean(tb_iterator_ref_t iterator, tb_cpointer_t item, tb_cpointer_t value)
{
    // the worker pull
    tb_thread_pool_worker_t* worker = (tb_thread_pool_worker_t*)value;
    tb_assert_abort(worker && worker->jobs && worker->stats);

    // the job
    tb_thread_pool_job_t* job = (tb_thread_pool_job_t*)item;
    tb_assert_abort(job);

    // the job state
    tb_size_t state = tb_atomic_get(&job->state);

    // waiting and non-full? pull it
    tb_bool_t ok = tb_false;
    if (state == TB_STATE_WAITING && worker->pull < TB_THREAD_POOL_JOBS_PULL_TIME_MAXN)
    {
        // append the job to the working jobs
        tb_vector_insert_tail(worker->jobs, job);   

        // computate the job average time 
        tb_size_t average_time = 200;
        if (tb_hash_map_size(worker->stats))
        {
            tb_thread_pool_job_stats_t* stats = (tb_thread_pool_job_stats_t*)tb_hash_map_get(worker->stats, job->task.done);
            if (stats && stats->done_count) average_time = (tb_size_t)(stats->total_time / stats->done_count);
        }

        // update the pull time
        worker->pull += average_time;

        // trace
        tb_trace_d("worker[%lu]: pull: task[%p:%s] from pending", worker->id, job->task.done, job->task.name);
    }
    // finished or killed? remove it
    else if (state == TB_STATE_FINISHED || state == TB_STATE_KILLED)
    {
        // trace
        tb_trace_d("worker[%lu]: remove: task[%p:%s] from pending", worker->id, job->task.done, job->task.name);

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

        // remove it from the waiting or urgent jobs
        ok = tb_true;

        // refn--
        if (job->refn > 1) job->refn--;
        // remove it from pool directly
        else 
        {
            // the pool
            tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)worker->pool;
            tb_assert_abort(impl);

            // remove it from the jobs pool
            tb_fixed_pool_free(impl->jobs_pool, job);
        }
    }

    // remove it?
    return ok;
}
Esempio n. 13
0
tb_void_t tb_stack_put(tb_stack_ref_t stack, tb_cpointer_t data)
{
    tb_vector_insert_tail((tb_vector_ref_t)stack, data);
}