高精度定時器的使用

tbox內部提供了兩種定時器實現:timer和ltimerlinux

  • timer: 高精度版本,採用最小堆實現,複雜度是:O(log(n))
  • ltimer: 低精度版本,採用linux內核中的timing-wheel算法,複雜度是:O(1)

這裏主要講解下,如何使用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);
}

相關文章
相關標籤/搜索