一種高性能定時器——時間輪的實現

(1)時間輪樣貌

 (2)源代碼及註釋

#ifndef TIME_WHEEL
#define TIME_WHEEL

#include <stdio.h>
#include <math.h>

template <typename T> //T是客戶類,應包含定時器
class tw_timer //定時器類
{
public:
    int rotation; //時間輪轉多少圈後定時器會到期
    T *user_data; //客戶數據

    //定時器存於鏈表中
    tw_timer *prev;  //指向後繼節點
    tw_timer *next; //指向前驅節點

    void (*cb_func)(T*); //定時器到期時調用的函數
public:
    tw_timer(int _rota, T *_user, void (*_cb_func)(T*))
    :rotation(_rota), user_data(_user), cb_func(_cb_func),
     prev(NULL), next(NULL) { };
    
    //默認構造函數,用於構造時間輪上各鏈表的頭結點
    tw_timer(): prev(NULL), next(NULL) { };
};

template <typename T>
class time_wheel //時間輪類
{
private:
    int N; //時間輪上的槽的個數
    int SI; //時間輪轉動一步所表示的時間跨度,通常以秒爲單位

    //指向包含N個定時器對象的數組,以此表示時間輪
    //這裏的每個定時器對象都只是各槽所擁有的鏈表的頭結點
    tw_timer<T>* slots; 
    int cur_slot; //當前指針指向的槽
public:
    //構造函數,創建各鏈表的頭結點
    time_wheel(int _N, int _SI)
    :N(_N), SI(_SI),slots(new tw_timer<T>[N]), cur_slot(0) { };

    ~time_wheel()
    {
        for(int i = 0;i < N;++i)
        {
            //將各鏈表除頭結點之外的結點都銷燬
            tw_timer<T> *cur = slots[i].next, *temp;
            while(cur)
            {
                temp = cur->next;
                delete cur;
                cur = temp;
            }
        }
        delete[] slots; //銷燬頭結點數組
    }
public:
    //給定定時時間,客戶數據以及回調函數,創建一個定時器並插入到時間輪中,最後返回
    tw_timer<T>* add_timer(int timeout, T *user, void (*cb_func)(T*))
    {
        if(timeout <= 0)
        {
            return NULL;
        }
        //每一步的時間跨度不一定能整除定時時間,這裏向上取整
        int n_slot = ceil((double)timeout/SI);

        int rotation = n_slot/N; //計算時間輪需要轉的圈數
        int time_slot = (cur_slot + n_slot)%N; //計算此定時器將插入的槽

        //動態創建一個定時器
        tw_timer<T> *timer = new tw_timer<T>(rotation, user, cb_func);

        //將定時器插入對應的槽所擁有的鏈表內
        timer->next = slots[time_slot].next;
        timer->prev = &slots[time_slot];
        if(slots[time_slot].next)
        {
            slots[time_slot].next->prev = timer;
        }
        slots[time_slot].next = timer;

        return timer;
    }
    //給定一個定時器,將其從時間輪上刪除
    void del_timer(tw_timer<T>* timer)
    {
        if(!timer)
        {
            return;
        }
        timer->prev->next = timer->next;
        if(timer->next)
        {
            timer->next->prev = timer->prev;
        }
        delete timer;
    }
    //時間輪每轉動一步,就檢查指針指向的當前槽內有無定時器到期
    void tick()
    {
        cur_slot = (cur_slot + 1)%N; //時間輪向前轉動一步,指針指向下一個槽
        tw_timer<T> *cur = slots[cur_slot].next, *temp; //獲得首個定時器結點

        while(cur)
        {
            temp = cur->next;
            if(!cur->rotation) //若定時器內的圈數爲0,則表明此定時器到期
            {
                cur->cb_func(cur->user_data); //執行回調函數
                del_timer(cur); //刪除定時器
            }
            else
            {
                cur->rotation--; //圈數減1
            }
            cur = temp;
        }
    }
};

#endif

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章