tb_void_t tb_timer_task_exit(tb_timer_ref_t timer, tb_timer_task_ref_t task) { // check tb_timer_impl_t* impl = (tb_timer_impl_t*)timer; tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)task; tb_assert_and_check_return(impl && impl->pool && task_impl); // trace tb_trace_d("exit: when: %lld, period: %u, refn: %u", task_impl->when, task_impl->period, task_impl->refn); // enter tb_spinlock_enter(&impl->lock); // remove it? if (task_impl->refn > 1) { // refn-- task_impl->refn--; // cancel task task_impl->func = tb_null; task_impl->priv = tb_null; task_impl->repeat = 0; } // remove it from pool directly if the task_impl have been expired else tb_fixed_pool_free(impl->pool, task_impl); // leave tb_spinlock_leave(&impl->lock); }
tb_void_t tb_aico_exit(tb_aico_ref_t aico) { // 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(impl && aicp_impl && aicp_impl->pool); // wait closing? tb_size_t tryn = 15; while (tb_atomic_get(&impl->state) != TB_STATE_CLOSED && tryn--) { // trace tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: wait: ..", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state))); // wait some time tb_msleep(200); } // check tb_assert_abort(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); tb_check_return(tb_atomic_get(&impl->state) == TB_STATE_CLOSED); // enter tb_spinlock_enter(&aicp_impl->lock); // trace tb_trace_d("exit[%p]: type: %lu, handle: %p, state: %s: ok", aico, tb_aico_type(aico), impl->handle, tb_state_cstr(tb_atomic_get(&impl->state))); // free it tb_fixed_pool_free(aicp_impl->pool, aico); // leave tb_spinlock_leave(&aicp_impl->lock); }
static tb_void_t tb_aiop_aioo_exit(tb_aiop_impl_t* impl, tb_aioo_ref_t aioo) { // check tb_assert_and_check_return(impl && impl->pool); // enter tb_spinlock_enter(&impl->lock); // exit aioo if (aioo) tb_fixed_pool_free(impl->pool, aioo); // leave tb_spinlock_leave(&impl->lock); }
static tb_bool_t tb_thread_pool_worker_walk_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); // 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); // finished or killed? remove it tb_bool_t ok = tb_false; 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 pending 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; }
tb_void_t gb_mesh_face_list_kill(gb_mesh_face_list_ref_t list, gb_mesh_face_ref_t face) { // check gb_mesh_face_list_impl_t* impl = (gb_mesh_face_list_impl_t*)list; tb_assert_and_check_return(impl && impl->pool && face); #ifdef __gb_debug__ // check tb_assert_abort(face->id); // clear id face->id = 0; #endif // remove from the face list tb_list_entry_remove(&impl->head, &face->entry); // exit it tb_fixed_pool_free(impl->pool, face); }
static tb_void_t tb_demo_spider_task_exit(tb_demo_spider_task_t* task) { // check tb_assert_and_check_return(task); // the spider tb_demo_spider_t* spider = task->spider; tb_assert_and_check_return(spider); // trace tb_trace_d("task: exit: %s", task->iurl); // enter tb_spinlock_enter(&spider->lock); // exit task if (spider->pool) tb_fixed_pool_free(spider->pool, task); // leave tb_spinlock_leave(&spider->lock); }
tb_void_t tb_thread_pool_task_exit(tb_thread_pool_ref_t pool, tb_thread_pool_task_ref_t task) { // check tb_thread_pool_impl_t* impl = (tb_thread_pool_impl_t*)pool; tb_thread_pool_job_t* job = (tb_thread_pool_job_t*)task; tb_assert_and_check_return(impl && job); // kill it first tb_thread_pool_task_kill(pool, task); // enter tb_spinlock_enter(&impl->lock); // refn-- if (job->refn > 1) job->refn--; // remove it from pool directly else tb_fixed_pool_free(impl->jobs_pool, job); // leave tb_spinlock_leave(&impl->lock); }
tb_size_t tb_list_remove(tb_list_ref_t self, tb_size_t itor) { // check tb_list_t* list = (tb_list_t*)self; tb_assert_and_check_return_val(list && list->pool && itor, 0); // the node tb_list_entry_ref_t node = (tb_list_entry_ref_t)itor; tb_assert_and_check_return_val(node, tb_iterator_tail(self)); // the next node tb_list_entry_ref_t next = tb_list_entry_next(node); // remove node tb_list_entry_remove(&list->head, node); // free node tb_fixed_pool_free(list->pool, node); // the next node return (tb_size_t)next; }
tb_void_t gb_mesh_edge_list_kill(gb_mesh_edge_list_ref_t list, gb_mesh_edge_ref_t edge) { // check gb_mesh_edge_list_impl_t* impl = (gb_mesh_edge_list_impl_t*)list; tb_assert_and_check_return(impl && impl->pool && edge); // make sure the edge points to the first half-edge if (edge->sym < edge) edge = edge->sym; #ifdef __gb_debug__ // check tb_assert(edge->id && edge->sym->id); // clear id edge->id = 0; edge->sym->id = 0; #endif // remove it from the list gb_mesh_edge_remove_done(edge); // exit it tb_fixed_pool_free(impl->pool, edge); }
tb_bool_t tb_timer_spak(tb_timer_ref_t timer) { // check tb_timer_impl_t* impl = (tb_timer_impl_t*)timer; tb_assert_and_check_return_val(impl && impl->pool && impl->heap, tb_false); // stoped? tb_check_return_val(!tb_atomic_get(&impl->stop), tb_false); // enter tb_spinlock_enter(&impl->lock); // done tb_bool_t ok = tb_false; tb_timer_task_func_t func = tb_null; tb_cpointer_t priv = tb_null; tb_bool_t killed = tb_false; do { // empty? if (!tb_heap_size(impl->heap)) { ok = tb_true; break; } // the top task tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)tb_heap_top(impl->heap); tb_assert_and_check_break(task_impl); // check refn tb_assert(task_impl->refn); // the now tb_hong_t now = tb_timer_now(impl); // timeout? if (task_impl->when <= now) { // pop it tb_heap_pop(impl->heap); // save func and data for calling it later func = task_impl->func; priv = task_impl->priv; // killed? killed = task_impl->killed? tb_true : tb_false; // repeat? if (task_impl->repeat) { // update when task_impl->when = now + task_impl->period; // continue task_impl tb_heap_put(impl->heap, task_impl); } else { // refn-- if (task_impl->refn > 1) task_impl->refn--; // remove it from pool directly else tb_fixed_pool_free(impl->pool, task_impl); } } // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&impl->lock); // done func if (func) func(killed, priv); // ok? return ok; }
static tb_thread_pool_job_t* tb_thread_pool_jobs_post_task(tb_thread_pool_impl_t* impl, tb_thread_pool_task_t const* task, tb_size_t* post_size) { // check tb_assert_and_check_return_val(impl && task && task->done && post_size, tb_null); // done tb_bool_t ok = tb_false; tb_thread_pool_job_t* job = tb_null; do { // check tb_assert_and_check_break(tb_list_entry_size(&impl->jobs_waiting) + tb_list_entry_size(&impl->jobs_urgent) + 1 < TB_THREAD_POOL_JOBS_WAITING_MAXN); // make job job = (tb_thread_pool_job_t*)tb_fixed_pool_malloc0(impl->jobs_pool); tb_assert_and_check_break(job); // init job job->refn = 1; job->state = TB_STATE_WAITING; job->task = *task; // non-urgent job? if (!task->urgent) { // post to the waiting jobs tb_list_entry_insert_tail(&impl->jobs_waiting, &job->entry); } else { // post to the urgent jobs tb_list_entry_insert_tail(&impl->jobs_urgent, &job->entry); } // the waiting jobs count tb_size_t jobs_waiting_count = tb_list_entry_size(&impl->jobs_waiting) + tb_list_entry_size(&impl->jobs_urgent); tb_assert_and_check_break(jobs_waiting_count); // update the post size if (*post_size < impl->worker_size) (*post_size)++; // trace tb_trace_d("task[%p:%s]: post: %lu: ..", task->done, task->name, *post_size); // init them if the workers have been not inited if (impl->worker_size < jobs_waiting_count) { tb_size_t i = impl->worker_size; tb_size_t n = tb_min(jobs_waiting_count, impl->worker_maxn); for (; i < n; i++) { // the worker tb_thread_pool_worker_t* worker = &impl->worker_list[i]; // clear worker tb_memset(worker, 0, sizeof(tb_thread_pool_worker_t)); // init worker worker->id = i; worker->pool = (tb_thread_pool_ref_t)impl; worker->loop = tb_thread_init(__tb_lstring__("thread_pool"), tb_thread_pool_worker_loop, worker, impl->stack); tb_assert_and_check_continue(worker->loop); } // update the worker size impl->worker_size = i; } // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it tb_fixed_pool_free(impl->jobs_pool, job); job = tb_null; } // ok? return job; }
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; }