Example #1
0
tb_bool_t tb_aico_open_sock(tb_aico_ref_t aico, tb_socket_ref_t sock)
{
    // check
    tb_aico_impl_t* impl = (tb_aico_impl_t*)aico;
    tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp;
    tb_assert_and_check_return_val(impl && sock && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false);

    // done
    tb_bool_t ok = tb_false;
    do
    {
        // closed?
        tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED);
        tb_assert_and_check_break(!impl->type && !impl->handle);

        // bind type and handle
        impl->type     = TB_AICO_TYPE_SOCK;
        impl->handle   = (tb_handle_t)sock;

        // addo aico
        ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl);
        tb_assert_and_check_break(ok);

        // opened
        tb_atomic_set(&impl->state, TB_STATE_OPENED);

    } while (0);

    // ok?
    return ok;
}
Example #2
0
static tb_bool_t tb_async_transfer_open_func(tb_async_transfer_impl_t* impl, tb_size_t state, tb_hize_t offset, tb_hong_t size, tb_async_transfer_open_func_t func, tb_cpointer_t priv)
{
    // check
    tb_assert_and_check_return_val(impl, tb_false);

    // ok?
    tb_bool_t ok = tb_true;
    if (state == TB_STATE_OK) 
    {
        // opened
        tb_atomic_set(&impl->state, TB_STATE_OPENED);

        // done func
        if (func) ok = func(state, offset, size, priv);
    }
    // failed? 
    else 
    {
        // init func and state
        impl->clos_opening.func   = func;
        impl->clos_opening.priv   = priv;
        impl->clos_opening.state  = state;

        // close it
        ok = tb_async_transfer_clos((tb_async_transfer_ref_t)impl, tb_async_transfer_clos_opening_func, impl);
    }

    // ok?
    return ok;
}
Example #3
0
tb_bool_t tb_aico_open_task(tb_aico_ref_t aico, tb_bool_t ltimer)
{
    // check
    tb_aico_impl_t* impl = (tb_aico_impl_t*)aico;
    tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp;
    tb_assert_and_check_return_val(impl && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false);

    // done
    tb_bool_t ok = tb_false;
    do
    {
        // closed?
        tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED);
        tb_assert_and_check_break(!impl->type);

        // bind type and handle
        // hack: handle != null? using higher precision timer for being compatible with sock/file task
        impl->type     = TB_AICO_TYPE_TASK;
        impl->handle   = (tb_handle_t)(tb_size_t)!ltimer;

        // addo aico
        ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl);
        tb_assert_and_check_break(ok);

        // opened
        tb_atomic_set(&impl->state, TB_STATE_OPENED);

    } while (0);

    // ok?
    return ok;
}
Example #4
0
tb_bool_t tb_semaphore_post(tb_semaphore_ref_t semaphore, tb_size_t post)
{
    // check
    tb_semaphore_impl_t* impl = (tb_semaphore_impl_t*)semaphore;
    tb_assert_and_check_return_val(semaphore && impl->semaphore && impl->semaphore != INVALID_HANDLE_VALUE && post, tb_false);
    
    // += post
    tb_atomic_fetch_and_add(&impl->value, post);
    
    // post
    LONG prev = 0;
    if (!ReleaseSemaphore(impl->semaphore, (LONG)post, &prev) && prev >= 0) 
    {
        // restore
        tb_atomic_fetch_and_sub(&impl->value, (tb_long_t)post);
        return tb_false;
    }

    // check
    tb_assert_and_check_return_val(prev + post <= TB_SEMAPHORE_VALUE_MAXN, tb_false);
    
    // save value
    tb_atomic_set(&impl->value, prev + post);
    
    // ok
    return tb_true;
}
Example #5
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_void_t tb_async_transfer_clos_func(tb_async_transfer_impl_t* impl, tb_size_t state)
{
    // check
    tb_assert_and_check_return(impl && impl->clos.func);
         
    // trace
    tb_trace_d("closed");

    // closed
    tb_atomic_set(&impl->state, TB_STATE_CLOSED);

    // clear pause state
    tb_atomic_set(&impl->state_pause, TB_STATE_OK);

    // done func
    impl->clos.func(state, impl->clos.priv);
}
Example #6
0
tb_bool_t tb_async_stream_open_func(tb_async_stream_ref_t stream, tb_size_t state, tb_async_stream_open_func_t func, tb_cpointer_t priv)
{
    // check
    tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
    tb_assert_and_check_return_val(impl, tb_false);

    // ok?
    tb_bool_t ok = tb_true;
    if (state == TB_STATE_OK) 
    {
        // opened
        tb_atomic_set(&impl->istate, TB_STATE_OPENED);

        // done func
        if (func) ok = func(stream, state, priv);
    }
    // failed? 
    else 
    {
        // try closing ok?
        if (impl->clos_try && impl->clos_try(stream))
        {
            // closed
            tb_atomic_set(&impl->istate, TB_STATE_CLOSED);

            // done func
            if (func) func(stream, state, priv);
        }
        else
        {
            // check
            tb_assert_and_check_return_val(impl->clos, tb_false);

            // init func and state
            impl->clos_opening.func   = func;
            impl->clos_opening.priv   = priv;
            impl->clos_opening.state  = state;

            // close it
            ok = impl->clos(stream, tb_async_stream_clos_opening, tb_null);
        }
    }

    // ok?
    return ok;
}
Example #7
0
tb_void_t gb_quality_set(tb_size_t quality)
{
    // check
    tb_assert_and_check_return(quality <= GB_QUALITY_TOP);

    // save quality
    tb_atomic_set(&g_quality, quality);
}
Example #8
0
tb_void_t tb_async_transfer_limitrate(tb_async_transfer_ref_t transfer, tb_size_t rate)
{
    // check
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
    tb_assert_and_check_return(impl);

    // set the limited rate
    tb_atomic_set(&impl->limited_rate, rate);
}
Example #9
0
tb_void_t tb_async_stream_open_done(tb_async_stream_ref_t stream)
{
    // check
    tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
    tb_assert_and_check_return(impl);

    // opened or closed?
    tb_atomic_set(&impl->istate, TB_STATE_OPENED);
}
Example #10
0
tb_void_t tb_aico_timeout_set(tb_aico_ref_t aico, tb_size_t type, tb_long_t timeout)
{
    // check
    tb_aico_impl_t* impl = (tb_aico_impl_t*)aico;
    tb_assert_and_check_return(impl && type < tb_arrayn(impl->timeout));

    // set the impl timeout
    tb_atomic_set((tb_atomic_t*)(impl->timeout + type), timeout);
}
Example #11
0
tb_bool_t tb_async_transfer_clos_try(tb_async_transfer_ref_t transfer)
{
    // check
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
    tb_assert_and_check_return_val(impl, tb_false);

    // trace
    tb_trace_d("clos: try: ..");
       
    // done
    tb_bool_t ok = tb_false;
    do
    {
        // closed?
        if (TB_STATE_CLOSED == tb_atomic_get(&impl->state))
        {
            ok = tb_true;
            break;
        }

        // try closing istream
        if (impl->istream && !tb_async_stream_clos_try(impl->istream)) break;

        // try closing ostream
        if (impl->ostream && !tb_async_stream_clos_try(impl->ostream)) break;

        // closed
        tb_atomic_set(&impl->state, TB_STATE_CLOSED);

        // clear pause state
        tb_atomic_set(&impl->state_pause, TB_STATE_OK);

        // ok
        ok = tb_true;
        
    } while (0);

    // trace
    tb_trace_d("clos: try: %s", ok? "ok" : "no");
         
    // ok?
    return ok;
}
Example #12
0
static tb_void_t tb_demo_spider_exit(tb_demo_spider_t* spider)
{
    // check
    tb_assert_and_check_return(spider);

    // trace
    tb_trace_d("exit: ..");

    // kill it
    tb_atomic_set(&spider->state, TB_STATE_KILLING);

    // kill all transfer tasks
    tb_transfer_pool_kill_all(tb_transfer_pool());

    // kill all parser tasks
    tb_thread_pool_task_kill_all(tb_thread_pool());

    // wait all transfer tasks exiting
    tb_transfer_pool_wait_all(tb_transfer_pool(), -1);

    // wait all parser tasks exiting
    tb_thread_pool_task_wait_all(tb_thread_pool(), -1);

    // enter
    tb_spinlock_enter(&spider->lock);

    // exit filter
    if (spider->filter) tb_bloom_filter_exit(spider->filter);
    spider->filter = tb_null;

    // exit pool
    if (spider->pool) tb_fixed_pool_exit(spider->pool);
    spider->pool = tb_null;

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

    // exit lock
    tb_spinlock_exit(&spider->lock);

    // exit home
    tb_url_exit(&spider->home);

    // exit option
#ifdef TB_CONFIG_MODULE_HAVE_OBJECT
    if (spider->option) tb_option_exit(spider->option);
    spider->option = tb_null;
#endif

    // trace
    tb_trace_d("exit: ok");
}
Example #13
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
tb_bool_t tb_android_init(JavaVM* jvm)
{
    // check
    if (!jvm)
    {
        // warning
        tb_trace_w("the java machine be not inited, please pass it to the tb_init function!");
    }

    // init it
    tb_atomic_set(&g_jvm, (tb_size_t)jvm);

    // ok
    return tb_true;
}
Example #14
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * implementation
 */
static tb_void_t tb_async_stream_clos_opening(tb_async_stream_ref_t stream, tb_size_t state, tb_cpointer_t priv)
{
    // check
    tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
    tb_assert_and_check_return(impl);

    // trace
    tb_trace_d("clos: opening: %s, state: %s", tb_url_cstr(&impl->url), tb_state_cstr(impl->clos_opening.state));

    // closed
    tb_atomic_set(&impl->istate, TB_STATE_CLOSED);

    // done func
    if (impl->clos_opening.func) impl->clos_opening.func(stream, impl->clos_opening.state, impl->clos_opening.priv);
}
Example #15
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * private interfaces
 */
tb_void_t tb_async_stream_clear(tb_async_stream_ref_t stream)
{
    // check
    tb_async_stream_impl_t* impl = tb_async_stream_impl(stream);
    tb_assert_and_check_return(impl);

    // clear rcache
    tb_buffer_clear(&impl->rcache_data);

    // clear wcache
    tb_buffer_clear(&impl->wcache_data);

    // clear istate
    tb_atomic_set(&impl->istate, TB_STATE_CLOSED);
}
Example #16
0
tb_void_t tb_timer_exit(tb_timer_ref_t timer)
{
    // check
    tb_timer_impl_t* impl = (tb_timer_impl_t*)timer;
    tb_assert_and_check_return(impl);

    // stop it
    tb_atomic_set(&impl->stop, 1);

    // wait loop exit
    tb_size_t tryn = 10;
    while (tb_atomic_get(&impl->work) && tryn--) tb_msleep(500);

    // warning
    if (!tryn && tb_atomic_get(&impl->work)) tb_trace_w("[timer]: the loop has been not exited now!");

    // post event
    tb_spinlock_enter(&impl->lock);
    tb_event_ref_t event = impl->event;
    tb_spinlock_leave(&impl->lock);
    if (event) tb_event_post(event);

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

    // exit heap
    if (impl->heap) tb_heap_exit(impl->heap);
    impl->heap = tb_null;

    // exit pool
    if (impl->pool) tb_fixed_pool_exit(impl->pool);
    impl->pool = tb_null;

    // exit event
    if (impl->event) tb_event_exit(impl->event);
    impl->event = tb_null;

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

    // exit lock
    tb_spinlock_exit(&impl->lock);

    // exit it
    tb_free(impl);
}
Example #17
0
tb_bool_t tb_aico_open_file_from_path(tb_aico_ref_t aico, tb_char_t const* path, tb_size_t mode)
{
    // check
    tb_aico_impl_t* impl = (tb_aico_impl_t*)aico;
    tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)impl->aicp;
    tb_assert_and_check_return_val(impl && path && aicp_impl && aicp_impl->ptor && aicp_impl->ptor->addo, tb_false);

    // done
    tb_bool_t       ok = tb_false;
    tb_file_ref_t   file = tb_null;
    do
    {
        // closed?
        tb_assert_and_check_break(tb_atomic_get(&impl->state) == TB_STATE_CLOSED);
        tb_assert_and_check_break(!impl->type && !impl->handle);

        // init file
        file = tb_file_init(path, mode | TB_FILE_MODE_ASIO);
        tb_assert_and_check_break(file);

        // bind type and handle
        impl->type     = TB_AICO_TYPE_FILE;
        impl->handle   = (tb_handle_t)file;

        // addo aico
        ok = aicp_impl->ptor->addo(aicp_impl->ptor, impl);
        tb_assert_and_check_break(ok);

        // opened
        tb_atomic_set(&impl->state, TB_STATE_OPENED);

    } while (0);

    // failed?
    if (!ok)
    {
        // exit it
        if (file) tb_file_exit(file);
        file = tb_null;
    }

    // ok?
    return ok;
}
Example #18
0
File: tbox.c Project: waruqi/tbox
tb_void_t tb_exit()
{
    // have been exited?
    if (TB_STATE_OK != tb_atomic_fetch_and_pset(&g_state, TB_STATE_OK, TB_STATE_EXITING)) return ;

    // kill singleton
    tb_singleton_kill();

    // exit object
#ifdef TB_CONFIG_MODULE_HAVE_OBJECT
    tb_object_exit_env();
#endif
    
    // exit network envirnoment
    tb_network_exit_env();
     
    // exit libm envirnoment
    tb_libm_exit_env();
     
    // exit math envirnoment
    tb_math_exit_env();
    
    // exit libc envirnoment
    tb_libc_exit_env();
    
    // exit platform envirnoment
    tb_platform_exit_env();
    
    // exit singleton
    tb_singleton_exit();

    // exit memory envirnoment
    tb_memory_exit_env();

    // trace
    tb_trace_d("exit: ok");

    // exit trace
    tb_trace_exit();

    // end
    tb_atomic_set(&g_state, TB_STATE_END);
}
Example #19
0
tb_void_t tb_thread_pool_kill(tb_thread_pool_ref_t pool)
{
    // check
    tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)pool;
    tb_assert_and_check_return(impl);

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

    // kill it
    tb_size_t post = 0;
    if (!impl->bstoped)
    {
        // trace
        tb_trace_d("kill: ..");

        // stoped
        impl->bstoped = tb_true;
        
        // kill all workers
        tb_size_t i = 0;
        tb_size_t n = impl->worker_size;
        for (i = 0; i < n; i++) tb_atomic_set(&impl->worker_list[i].bstoped, 1);

        // kill all jobs
        if (impl->jobs_pool) tb_fixed_pool_walk(impl->jobs_pool, tb_thread_pool_jobs_walk_kill_all, tb_null);

        // post it
        post = impl->worker_size;
    }

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

    // post the workers
    if (post) tb_thread_pool_worker_post(impl, post);
}
Example #20
0
static tb_long_t tb_aiop_spak_clos(tb_aiop_ptor_impl_t* impl, tb_aice_ref_t aice)
{
    // check
    tb_assert_and_check_return_val(impl && impl->aiop && impl->ltimer && impl->timer && aice, -1);
    tb_assert_and_check_return_val(aice->code == TB_AICE_CODE_CLOS, -1);

    // the aico
    tb_aiop_aico_t* aico = (tb_aiop_aico_t*)aice->aico;
    tb_assert_and_check_return_val(aico, -1);

    // trace
    tb_trace_d("clos: aico: %p, code: %u: %s", aico, aice->code, tb_state_cstr(tb_atomic_get(&aico->base.state)));

    // exit the timer task
    if (aico->task)
    {
        if (aico->bltimer) tb_ltimer_task_exit(impl->ltimer, aico->task);
        else tb_timer_task_exit(impl->timer, aico->task);
        aico->bltimer = 0;
    }
    aico->task = tb_null;

    // exit the sock
    if (aico->base.type == TB_AICO_TYPE_SOCK)
    {
        // remove aioo
        if (aico->aioo) tb_aiop_delo(impl->aiop, aico->aioo);
        aico->aioo = tb_null;

        // close the socket handle
        if (aico->base.handle) tb_socket_exit((tb_socket_ref_t)aico->base.handle);
        aico->base.handle = tb_null;
    }
    // exit file
    else if (aico->base.type == TB_AICO_TYPE_FILE)
    {
        // exit the file handle
        if (aico->base.handle) tb_file_exit((tb_file_ref_t)aico->base.handle);
        aico->base.handle = tb_null;
    }

    // clear waiting state
    aico->waiting = 0;
    aico->wait_ok = 0;
    aico->aice.code = TB_AICE_CODE_NONE;

    // clear type
    aico->base.type = TB_AICO_TYPE_NONE;

    // clear timeout
    tb_size_t i = 0;
    tb_size_t n = tb_arrayn(aico->base.timeout);
    for (i = 0; i < n; i++) aico->base.timeout[i] = -1;

    // closed
    tb_atomic_set(&aico->base.state, TB_STATE_CLOSED);

    // ok
    aice->state = TB_STATE_OK;
    return 1;
}
Example #21
0
/* //////////////////////////////////////////////////////////////////////////////////////
 * main
 */ 
tb_int_t tb_demo_platform_semaphore_main(tb_int_t argc, tb_char_t** argv)
{
    // init loop
    tb_demo_loop_t  loop[10];
    tb_size_t       i = 0;
    tb_size_t       n = tb_arrayn(loop);
    for (i = 0; i < n; i++)
    {
        // init semaphore
        loop[i].semaphore = tb_semaphore_init(0); 
        tb_assert_and_check_break(loop[i].semaphore);

        // post semaphore
        tb_semaphore_post(loop[i].semaphore, 1);

        // init index
        loop[i].index = i;

        // init stoped
        loop[i].bstoped = 0;

        // init loop
        loop[i].loop = tb_thread_init(tb_null, tb_demo_loop, loop + i, 0);
        tb_assert_and_check_break(loop[i].loop);
    }

    // check
    tb_assert_and_check_return_val(i == n, 0);

    // wait some time
    tb_msleep(100);

    // post
    tb_char_t line[256];
    tb_bool_t stop = tb_false;
    while (!stop)
    {
        // get line
        tb_char_t const* p = tb_demo_gets(line, sizeof(line));
        tb_assert_and_check_break(p);

        // trace
        tb_trace_i("post: %s", p);

        // done
        while (*p && !stop)
        {
            tb_char_t ch = *p++;
            switch (ch)
            {
            case 'q':
                stop = tb_true;
                break;
            default:
                {
                    if (ch >= '0' && ch <= '9')
                    {
                        // the index
                        tb_size_t index = ch - '0';
                        tb_assert_and_check_break(index < n && index == loop[index].index);

                        // post semaphore
                        if (loop[index].semaphore) tb_semaphore_post(loop[index].semaphore, 1);
                    }
                }
                break;
            }
        }
    }

    // post loop
    for (i = 0; i < n; i++)
    {
        // quit thread
        tb_atomic_set(&loop[i].bstoped, 1);

        // post semaphore
        if (loop[i].semaphore) tb_semaphore_post(loop[i].semaphore, 1);
    }

    // exit loop
    for (i = 0; i < n; i++)
    {
        // exit loop
        if (loop[i].loop) 
        {
            // wait it
            if (!tb_thread_wait(loop[i].loop, 5000))
            {
                // trace
                tb_trace_e("wait loop[%lu]: timeout", i);
            }

            // exit it
            tb_thread_exit(loop[i].loop);
        }

        // exit semaphore
        if (loop[i].semaphore) tb_semaphore_exit(loop[i].semaphore);
    }

    // exit
    tb_trace_i("exit");
    return 0;
}
Example #22
0
tb_bool_t tb_async_transfer_open(tb_async_transfer_ref_t transfer, tb_hize_t offset, tb_async_transfer_open_func_t func, tb_cpointer_t priv)
{
    // check
    tb_async_transfer_impl_t* impl = (tb_async_transfer_impl_t*)transfer;
    tb_assert_and_check_return_val(impl && impl->aicp && func, tb_false);

    // done
    tb_bool_t ok = tb_false;
    do
    {
        // set opening
        tb_size_t state = tb_atomic_fetch_and_pset(&impl->state, TB_STATE_CLOSED, TB_STATE_OPENING);

        // opened? done func directly
        if (state == TB_STATE_OPENED)
        {
            // check
            tb_assert_and_check_break(impl->istream && impl->ostream);

            // done func
            func(TB_STATE_OK, tb_async_stream_offset(impl->istream), tb_async_stream_size(impl->istream), priv);

            // ok
            ok = tb_true;
            break;
        }

        // must be closed
        tb_assert_and_check_break(state == TB_STATE_CLOSED);

        // clear pause state
        tb_atomic_set(&impl->state_pause, TB_STATE_OK);

        // init func
        impl->open.func = func;
        impl->open.priv = priv;

        // check
        tb_assert_and_check_break(impl->istream);
        tb_assert_and_check_break(impl->ostream);

        // init some rate info
        impl->done.base_time      = tb_aicp_time(impl->aicp);
        impl->done.base_time1s    = impl->done.base_time;
        impl->done.saved_size     = 0;
        impl->done.saved_size1s   = 0;
        impl->done.current_rate   = 0;

        // ctrl stream
        if (impl->ctrl.func && !impl->ctrl.func(impl->istream, impl->ostream, impl->ctrl.priv)) break;

        // open and seek istream
        if (!tb_async_stream_open_seek(impl->istream, offset, tb_async_transfer_istream_open_func, impl)) break;

        // ok
        ok = tb_true;

    } while (0);

    // failed? restore state
    if (!ok) tb_atomic_set(&impl->state, TB_STATE_CLOSED);

    // ok?
    return ok;
}
Example #23
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;
}
Example #24
0
tb_void_t tb_android_exit()
{
    // clear it
    tb_atomic_set(&g_jvm, 0);
}