tbox內部提供了兩種定時器實現:timer和ltimerlinux
這裏主要講解下,如何使用timer實現高精度的定時器任務,精確到ms級別,對於低精度的ltimer,能夠參考:低精度定時器的使用git
下面先給個簡單的例子來講明:github
/* 定義一個定時器任務處理函數 * * @param killed 表示當前任務是否被tb_timer_task_kill強行kill掉的 * @param priv 投遞任務時傳入的用戶自定義數據指針 */ static tb_void_t tb_demo_timer_task_func(tb_bool_t killed, tb_cpointer_t priv) { } /* 投遞一個定時器任務到全局timer中,間隔1000ms,會重複執行 * * 其中tb_true表示是否會重複執行,若是設爲tb_false,那麼只會執行一次 * tb_null參數,就是傳入給任務函數的用戶自定義數據指針 */ tb_timer_task_post(tb_timer(), 1000, tb_true, tb_demo_timer_task_func, tb_null);
上面的投遞,會在post調用完,馬上開始任務的計時和運行,若是想要在10s後,纔開始啓動定時器,能夠這麼投遞:算法
// 在10s後纔開始投遞一個定時器任務到全局timer中,間隔1000ms,會重複執行 tb_timer_task_post_after(tb_timer(), 10000, 1000, tb_true, tb_demo_timer_task_func, tb_null);
若是要肯定絕對投遞時間,能夠這麼投遞:緩存
// 在指定時間戳tb_time() + 150000纔開始投遞一個定時器任務到全局timer中,間隔1000ms,會重複執行 // 這裏至關於15s後纔開始投遞 tb_timer_task_post_at(tb_timer(), tb_time() + 150000, 1000, tb_true, tb_demo_timer_task_func, tb_null);
前面使用的post投遞接口,都是沒法維護和控制任務的,若是想要在某個特定的時刻取消還在執行隊列中的定時器任務安全
能夠使用下面的方式來維護:服務器
// 建立一個間隔10s的定時器任務,不會重複執行 tb_timer_task_ref_t task = tb_timer_task_init(tb_timer(), 10000, tb_false, tb_demo_timer_task_func, tb_null); // 過段時間後 // ... // 若是以爲不想執行這個任務了,能夠手動取消掉,這個是線程安全的 if (task) tb_timer_task_kill(tb_timer(), task); // 最後在程序退出時,銷燬這個任務資源 if (task) tb_timer_task_exit(tb_timer(), task);
前面的例子都是在全局的默認tb_timer()
中投遞的定時器任務,tbox會在後臺建立一個單獨的線程去維護它的全部任務,若是以爲這個太佔資源, 本身有特定線程在不斷loop的話能夠建立個獨立的timer,掛接到本身的loop線程中,重用線程資源:併發
// 假設這個是你本身的線程 static tb_pointer_t tb_demo_timer_loop(tb_cpointer_t priv) { // the timer tb_timer_ref_t timer = (tb_ltimer_ref_t)priv; #if 1 // 本身的線程loop while (1) { // 等待特定的定時器延時 // 不必定非得用sleep, 若是你的線程正在處理select/epoll等,能夠直接利用這些接口的timeout參數來等待 tb_sleep(tb_timer_delay(timer)); // 本身的一些其餘邏輯代碼 // ... // 固定調用,脈動一下定時器,很快的,不會長時間阻塞,除非有耗時的任務 tb_timer_spak(timer); } #else // 若是沒有其餘邏輯代碼,那麼能夠直接用timer自帶的loop來代替 tb_timer_loop(timer); #endif // exit it tb_thread_return(tb_null); return tb_null; } /* 建立一個定時器 * * 第一個參數:指定定時器最大併發任務規模,默承認以傳0,也能夠本身指定規模數 * 第二個參數:是否啓用時間戳緩存優化,傳tb_false就好了,這個通常用於服務器端高併發處理時的優化 */ tb_timer_ref_t timer = tb_timer_init(0, tb_false); if (timer) { // 投遞一些任務 // ... // 退出定時器 tb_timer_exit(timer); }