/* ////////////////////////////////////////////////////////////////////////////////////// * aioo */ static tb_aioo_ref_t tb_aiop_aioo_init(tb_aiop_impl_t* impl, tb_socket_ref_t sock, tb_size_t code, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(impl && impl->pool, tb_null); // enter tb_spinlock_enter(&impl->lock); // make aioo tb_aioo_impl_t* aioo = (tb_aioo_impl_t*)tb_fixed_pool_malloc0(impl->pool); // init aioo if (aioo) { aioo->code = code; aioo->priv = priv; aioo->sock = sock; } // leave tb_spinlock_leave(&impl->lock); // ok? return (tb_aioo_ref_t)aioo; }
/* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ tb_aico_ref_t tb_aico_init(tb_aicp_ref_t aicp) { // check tb_aicp_impl_t* aicp_impl = (tb_aicp_impl_t*)aicp; tb_assert_and_check_return_val(aicp_impl && aicp_impl->pool, tb_null); // enter tb_spinlock_enter(&aicp_impl->lock); // make aico tb_aico_impl_t* aico = (tb_aico_impl_t*)tb_fixed_pool_malloc0(aicp_impl->pool); // init aico if (aico) { aico->aicp = aicp; aico->type = TB_AICO_TYPE_NONE; aico->handle = tb_null; aico->state = TB_STATE_CLOSED; // init timeout tb_size_t i = 0; tb_size_t n = tb_arrayn(aico->timeout); for (i = 0; i < n; i++) aico->timeout[i] = -1; } // leave tb_spinlock_leave(&aicp_impl->lock); // ok? return (tb_aico_ref_t)aico; }
gb_mesh_face_ref_t gb_mesh_face_list_make(gb_mesh_face_list_ref_t list) { // check gb_mesh_face_list_impl_t* impl = (gb_mesh_face_list_impl_t*)list; tb_assert_and_check_return_val(impl && impl->pool, tb_null); // make it gb_mesh_face_ref_t face = (gb_mesh_face_ref_t)tb_fixed_pool_malloc0(impl->pool); tb_assert_and_check_return_val(face, tb_null); #ifdef __gb_debug__ // init id face->id = ++impl->id; // save list face->list = (tb_pointer_t)list; #endif // insert to the face list switch (impl->order) { case GB_MESH_ORDER_INSERT_HEAD: tb_list_entry_insert_head(&impl->head, &face->entry); break; case GB_MESH_ORDER_INSERT_TAIL: default: tb_list_entry_insert_tail(&impl->head, &face->entry); break; } // ok return face; }
tb_timer_task_ref_t tb_timer_task_init_at(tb_timer_ref_t timer, tb_hize_t when, tb_size_t period, tb_bool_t repeat, tb_timer_task_func_t func, tb_cpointer_t priv) { // check tb_timer_impl_t* impl = (tb_timer_impl_t*)timer; tb_assert_and_check_return_val(impl && impl->pool && impl->heap && func, tb_null); // stoped? tb_assert_and_check_return_val(!tb_atomic_get(&impl->stop), tb_null); // enter tb_spinlock_enter(&impl->lock); // make task tb_event_ref_t event = tb_null; tb_hize_t when_top = -1; tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)tb_fixed_pool_malloc0(impl->pool); if (task_impl) { // the top when if (tb_heap_size(impl->heap)) { tb_timer_task_impl_t* task_impl = (tb_timer_task_impl_t*)tb_heap_top(impl->heap); if (task_impl) when_top = task_impl->when; } // init task task_impl->refn = 2; task_impl->func = func; task_impl->priv = priv; task_impl->when = when; task_impl->period = period; task_impl->repeat = repeat? 1 : 0; // add task tb_heap_put(impl->heap, task_impl); // the event event = impl->event; } // leave tb_spinlock_leave(&impl->lock); // post event if the top task is changed if (event && task_impl && when < when_top) tb_event_post(event); // ok? return (tb_timer_task_ref_t)task_impl; }
gb_mesh_edge_ref_t gb_mesh_edge_list_make_loop(gb_mesh_edge_list_ref_t list, tb_bool_t is_ccw) { // check gb_mesh_edge_list_impl_t* impl = (gb_mesh_edge_list_impl_t*)list; tb_assert_and_check_return_val(impl && impl->pool, tb_null); // make it gb_mesh_edge_ref_t edge = (gb_mesh_edge_ref_t)tb_fixed_pool_malloc0(impl->pool); tb_assert_and_check_return_val(edge, tb_null); // the sym edge gb_mesh_edge_ref_t edge_sym = (gb_mesh_edge_ref_t)((tb_byte_t*)edge + impl->edge_size); // init edge edge->sym = edge_sym; edge->onext = edge_sym; edge->lnext = edge; // init sym edge edge_sym->sym = edge; edge_sym->onext = edge; edge_sym->lnext = edge_sym; #ifdef __gb_debug__ // init id edge->id = ++impl->id; edge_sym->id = edge->id; // save list edge->list = (tb_pointer_t)list; edge_sym->list = (tb_pointer_t)list; #endif // insert to the edge list switch (impl->order) { case GB_MESH_ORDER_INSERT_HEAD: gb_mesh_edge_insert_prev(edge, impl->head->next); break; case GB_MESH_ORDER_INSERT_TAIL: default: gb_mesh_edge_insert_prev(edge, impl->head); break; } // clockwise? reverse it return is_ccw? edge : edge_sym; }
static tb_transfer_task_t* tb_transfer_task_init(tb_transfer_pool_impl_t* impl, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv) { // check tb_assert_and_check_return_val(impl, tb_null); // done tb_bool_t ok = tb_false; tb_transfer_task_t* task = tb_null; do { // init task pool if (!impl->pool) impl->pool = tb_fixed_pool_init(tb_null, (impl->maxn >> 4) + 16, sizeof(tb_transfer_task_t), tb_null, tb_null, tb_null); tb_assert_and_check_break(impl->pool); // init task from the idle list first if (tb_list_entry_size(&impl->idle)) { // get the head entry tb_list_entry_ref_t entry = tb_list_entry_head(&impl->idle); tb_assert_and_check_break(entry); // the task task = (tb_transfer_task_t*)tb_list_entry(&impl->idle, entry); tb_assert_and_check_break(task); // remove the last task tb_list_entry_remove(&impl->idle, entry); // check tb_assert_and_check_break(task->transfer); } // init task from the task pool else { // make task task = (tb_transfer_task_t*)tb_fixed_pool_malloc0(impl->pool); tb_assert_and_check_break(task); // init transfer task->transfer = tb_async_transfer_init(impl->aicp, tb_true); tb_assert_and_check_break(task->transfer); } // init ctrl if (ctrl && !tb_async_transfer_ctrl(task->transfer, ctrl, priv)) break; // init task task->func = done; task->priv = priv; task->pool = impl; // ok ok = tb_true; } while (0); // failed? if (!ok) { // exit it if (task) tb_transfer_task_exit(impl, task); task = tb_null; } // ok? return task; }
static tb_bool_t tb_demo_spider_task_done(tb_demo_spider_t* spider, tb_char_t const* iurl, tb_bool_t* full) { // check tb_assert_and_check_return_val(spider && iurl, tb_false); // killed? tb_check_return_val(TB_STATE_OK == tb_atomic_get(&spider->state), tb_false); // only for home? if (spider->home_only && !tb_stristr(iurl, spider->home_domain)) { // trace tb_trace_d("task: done: %s: skip", iurl); return tb_true; } // enter tb_spinlock_enter(&spider->lock); // done tb_bool_t ok = tb_false; tb_size_t size = 0; tb_demo_spider_task_t* task = tb_null; tb_bool_t repeat = tb_false; do { // check tb_assert_and_check_break(spider->filter && spider->pool); // the task count size = tb_fixed_pool_size(spider->pool); // make the output url if (!tb_demo_spider_make_ourl(spider, iurl, spider->ourl, sizeof(spider->ourl) - 1)) break; // have been done already? if (!tb_bloom_filter_set(spider->filter, spider->ourl)) { // trace tb_trace_d("task: size: %lu, done: %s: repeat", size, iurl); // ok ok = tb_true; repeat = tb_true; break; } // trace tb_trace_d("task: size: %lu, done: %s: ..", size, iurl); // full? tb_check_break(size < TB_DEMO_SPIDER_TASK_MAXN); // make task task = (tb_demo_spider_task_t*)tb_fixed_pool_malloc0(spider->pool); tb_assert_and_check_break(task); // init task task->spider = spider; tb_strlcpy(task->iurl, iurl, sizeof(task->iurl) - 1); tb_strlcpy(task->ourl, spider->ourl, sizeof(task->ourl) - 1); // ok ok = tb_true; } while (0); // leave tb_spinlock_leave(&spider->lock); // ok? if (ok && !repeat) { // done ok = tb_false; do { // check tb_assert_and_check_break(task); // killed? tb_check_break(TB_STATE_OK == tb_atomic_get(&spider->state)); // repeat? if (tb_file_info(task->ourl, tb_null)) { // trace tb_trace_d("task: size: %lu, done: %s: repeat", size, iurl); // ok ok = tb_true; repeat = tb_true; break; } // done task ok = tb_transfer_pool_done(tb_transfer_pool(), task->iurl, task->ourl, 0, spider->limited_rate, tb_demo_spider_task_save, tb_demo_spider_task_ctrl, task); tb_assert_and_check_break(ok); } while (0); } // repeat or failed? if (repeat || !ok) { // exit task if (task) tb_demo_spider_task_exit(task); task = tb_null; // failed? if (!full && !ok) { // trace tb_trace_e("task: size: %lu, done: %s: post failed", size, iurl); } // save full if (full) *full = size < TB_DEMO_SPIDER_TASK_MAXN? tb_false : tb_true; } // 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; }