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"); }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_platform_thread_pool_main(tb_int_t argc, tb_char_t** argv) { #if 0 // post task: 60s tb_thread_pool_task_post(tb_thread_pool(), "60000ms", tb_demo_task_time_done, tb_null, (tb_cpointer_t)60000, tb_false); // post task: 10s tb_thread_pool_task_post(tb_thread_pool(), "10000ms", tb_demo_task_time_done, tb_null, (tb_cpointer_t)10000, tb_false); // post task: 1s tb_thread_pool_task_post(tb_thread_pool(), "1000ms", tb_demo_task_time_done, tb_demo_task_time_exit, (tb_cpointer_t)1000, tb_false); // wait some time getchar(); #else // done tb_size_t count = tb_random_range(tb_null, 1, 16); tb_size_t total = count; while (count-- && total < 1000) { // the time tb_size_t time = tb_random_range(tb_null, 0, 500); // trace tb_trace_i("post: %lu ms, total: %lu", time, total); // post task: time ms tb_thread_pool_task_post(tb_thread_pool(), tb_null, tb_demo_task_time_done, tb_demo_task_time_exit, (tb_pointer_t)time, !(time & 15)? tb_true : tb_false); // finished? wait some time and update count if (!count) { // wait some time tb_msleep(100); // update count count = tb_random_range(tb_null, 1, 16); total += count; } } // wait all tb_thread_pool_task_wait_all(tb_thread_pool(), -1); #endif // trace tb_trace_i("end"); return 0; }
tb_bool_t tb_thread_pool_exit(tb_thread_pool_ref_t pool) { // check tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)pool; tb_assert_and_check_return_val(impl, tb_false); // trace tb_trace_d("exit: .."); // kill it first tb_thread_pool_kill(pool); // wait all if (tb_thread_pool_task_wait_all(pool, 5000) <= 0) { // trace tb_trace_e("exit: wait failed!"); return tb_false; } /* exit all workers * need not lock it because the worker size will not be increase d */ tb_size_t i = 0; tb_size_t n = impl->worker_size; for (i = 0; i < n; i++) { // the worker tb_thread_pool_worker_t* worker = &impl->worker_list[i]; // exit loop if (worker->loop) { // wait it tb_long_t wait = 0; if ((wait = tb_thread_wait(worker->loop, 5000)) <= 0) { // trace tb_trace_e("worker[%lu]: wait failed: %ld!", i, wait); } // exit it tb_thread_exit(worker->loop); worker->loop = tb_null; } } impl->worker_size = 0; // enter tb_spinlock_enter(&impl->lock); // exit pending jobs tb_list_entry_exit(&impl->jobs_pending); // exit waiting jobs tb_list_entry_exit(&impl->jobs_waiting); // exit urgent jobs tb_list_entry_exit(&impl->jobs_urgent); // exit jobs pool if (impl->jobs_pool) tb_fixed_pool_exit(impl->jobs_pool); impl->jobs_pool = tb_null; // leave tb_spinlock_leave(&impl->lock); // exit lock tb_spinlock_exit(&impl->lock); // exit semaphore if (impl->semaphore) tb_semaphore_exit(impl->semaphore); impl->semaphore = tb_null; // exit it tb_free(impl); // trace tb_trace_d("exit: ok"); // ok return tb_true; }