色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

定時器作用及實現定時器數據結構選取介紹2

jf_78858299 ? 來源:程序員不是碼農 ? 作者:程序員不是碼農 ? 2023-04-21 15:20 ? 次閱讀

Skynet定時器實現方案

skynet中定時器數據結構

采用時間輪方式,hash表+鏈表實現,

struct timer_node {  //時間節點
 struct timer_node *next;
    uint32_t expire; //到期滴答數
};
struct link_list {  // 鏈表
  struct timer_node head;
  struct timer_node *tail;
};
struct timer {
 struct link_list near[256];  // 即將到來的定時器
    struct link_list t[4][64]; // 相對較遙遠的定時器
    struct spinlock lock;
    uint32_t time;  // 記錄當前滴答數
    uint64_t starttime;
    uint64_t current;
    uint64_t current_point;
};

其中time32位無符號整數, 記錄時間片對應數組near[256] ,表示即將到來的定時任務, t[4][64],表示較為遙遠的定時任務。

定時器執行流程

圖片

skynet_time_wheel

t[3] t[2] t[1] t[0] near
26-32位 20-26位 14-20位 8-14位 0-8位
[2^(8+6x3),2^(8+6x4)-1] [2^(8+6x2),2^(8+6x3)-1] [2^(8+6),2^(8+6x2)-1] [2^8,2^(8+6) -1] [0,2^8-1]
  • 首先檢查節點的expiretime的高24位是否相等,相等則將該節點添加到expire低8位值對應數組near的元素的鏈表中,不相等則進行下一步
  • 檢查expiretime的高18位是否相等,相等則將該節點添加到expire低第9位到第14位對應的6位二進制值對應數組t[0]的元素的鏈表中,否則進行下一步
  • 檢查expiretime的高12位是否相等,相等則將該節點添加到expire低第15位到第20位對應的6位二進制值對應數組t[1]的元素的鏈表中,如果不相等則進行下一步
  • 檢查expiretime的高6位是否相等,相等則將該節點添加到expire低第21位到第26位對應的6位二進制值對應數組t[2]的元素的鏈表中,如果不相等則進行下一步
  • 將該節點添加到expire低第27位到第32位對應的6位二進制值對應數組t[3]的元素的鏈表中

以下為具體實現,僅貼出主要接口,具體細節請參考skynet源代碼。

定時器初始化
// skynet_start.c
// skynet 啟動入口
void
skynet_start(struct skynet_config * config) {
    ...
    skynet_timer_init();
    ...
}
// skynet_timer.c
void
skynet_timer_init(void) {
    // 創建全局timer結構 TI
    TI  = timer_create_timer();
    uint32_t current = 0;
    systime(&TI->starttime, ¤t);
    TI->current = current;
    TI->current_point = gettime();
}
添加定時器

通過skynet_server.c中的cmd_timeout調用skynet_timeout添加新的定時器

// TI為全局的定時器指針
static struct timer * TI = NULL; 
int skynet_timeout(uint32_t handle, int time, int session) {
    ...
    struct timer_event event;
    event.handle = handle;  // callback
    eveng.session = session;
    // 添加新的定時器節點
    timer_add(TI, &event, sizeof(event), time);
    return session;
}
// 添加新的定時器節點
static void timer_add(struct timer *T, void 8arg, size_t sz, int time) {
    // 給timer_node指針分配空間,還需要分配timer_node + timer_event大小的空間,
    // 之后通過node + 1可獲得timer_event數據
    struct timer_node *node = (struct timer_node *)skynet_malloc(sizeof(*node)+sz);
    memcpy(node+1,arg,sz);
    SPIN_LOCK(T);
    node->expire=time+T->time;
    add_node(T, node);
    SPIN_UNLOCK(T);
}

// 添加到定時器鏈表里,如果定時器的到期滴答數跟當前比較近(<2^8),表示即將觸發定時器添加到T->near數組里
// 否則根據差值大小添加到對應的T->T[i]中
static void add_node(struct timer *T, struct timer_node *node) {
    ...
}
驅動方式

skynet啟動時,會創建一個線程專門跑定時器,每幀(0.0025s)調用skynet_updatetime()

// skynet_start.c
static void * 
thread_timer(void *p) {
    struct monitor * m = p;
    skynet_initthread(THREAD_TIMER);
    for (;;) {
        skynet_updatetime();  // 調用timer_update
        skynet_socket_updatetime();
        CHECK_ABORT
        wakeup(m,m->count-1);
        usleep(2500);  // 2500微秒 = 0.0025s
        if (SIG) {
            signal_hup();
            SIG = 0;
        }
    }
    ...
}

每個定時器設置一個到期滴答數,與當前系統的滴答數(啟動時為0,1滴答1滴答往后跳,1滴答==0.01s ) 比較得到差值interval;

如果interval比較小(0 <= interval <= 2^8-1),表示定時器即將到來,保存在第一部分前2^8個定時器鏈表中;否則找到屬于第二部分對用的層級中。

// skynet_timer.c
void 
skynet_updatetime(void) {
    ...
    uint32_t diff = (uint32_t)(cp - TI->current_point); 
    TI->current_point = cp;
    TI->current += diff;
    // diff單位為0.01s
    for (i = 0; i < diff; i++){
        timer_update(TI);        
    }
}
static void
timer_update(struct timer *T) {
    SPIN_LOCK(T);
    timer_execute(T); // 檢查T->near是否位空,有就處理到期定時器
    timer_shift(T);  // 時間片time++,移動高24位的鏈表
    timer_execute(T);
    SPIN_UNLOCK(T);
}
// 每幀從T->near中觸發到期得定時器
static inline void
timer_execute(struct timer *T) {
  ...
}
// 遍歷處理定時器鏈表中所有的定時器
static inline void
dispatch_list(struct timer_node *current) {
    ...
}
// 將高24位對應的4個6位的數組中的各個元素的鏈表往低位移
static void
timer_shift(struct timer *T) {
    ...
}
// 將level層的idx位置的定時器鏈表從當前位置刪除,并重新add_node
static void move_list(struct timer *T, int level, int idx) {

}

最小堆實現定時器

最小堆實現例子:boost.asio采用二叉樹,go采用四叉樹, libuv

具體實現略。

總結

本文主要介紹定時器作用,實現定時器數據結構選取,并詳細介紹了跳表,紅黑樹,時間輪實現定時器的思路和方法。

Python人工智能編程分享 Python 相關的技術文章、工具資料視頻教程等。專注Python編程開發學習以及人工智能、機器學習、自然語言處理、深度學習、圖像識別、語音識別無人駕駛等前沿AI技術學習!

公眾號

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11339

    瀏覽量

    210119
  • 定時器
    +關注

    關注

    23

    文章

    3255

    瀏覽量

    115169
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40190
收藏 人收藏

    評論

    相關推薦

    定時器/計數基礎

    15-1.實現定時的方法15-2.定時器/計數結構和工作原理 15-3.
    發表于 03-23 12:17 ?48次下載

    555定時器

    555定時器555定時器555定時器555定時器555定時器555定時器555
    發表于 11-10 17:25 ?52次下載

    基于51單片機的定時器2的操作與實現

    基于51單片機的定時器2的操作與實現,51單片機定時器2的使用!
    發表于 02-22 17:53 ?14次下載

    定時器介紹

    同時用兩個定時器控制蜂鳴器發聲, 定時器0控制頻率,定時器1控制同個 頻率持續的時間,間隔2s依次輸出 1,10,50100,200400800
    發表于 02-23 15:56 ?20次下載

    52單片機——定時器2詳解

    文章目錄前言一、定時器2簡述1.定時器2作用2.定時器
    發表于 11-11 12:51 ?19次下載
    52單片機——<b class='flag-5'>定時器</b><b class='flag-5'>2</b>詳解

    STC51定時器定時器中斷

    1.定義定時器介紹: 51單片機的定時器屬于單片機的內部資源,其電路的連接和運轉均在單片機內部完成。2.作用
    發表于 11-22 14:51 ?5次下載
    STC51<b class='flag-5'>定時器</b>與<b class='flag-5'>定時器</b>中斷

    stm32—定時器配置

    目錄定時器組成通用寄存通用寄存簡介:通用定時器 TIMx (TIM2-TIM5 )的功能:通用定時器
    發表于 11-22 17:51 ?11次下載
    stm32—<b class='flag-5'>定時器</b>配置

    STM32基于cubeMX實現定時器點燈

    Cortex M3內核當中的定時器,它并不屬于芯片廠商的外設,也就是說使用ARM內核的不同廠商,都擁有基本結構相同的系統定時器。主要目的是給RTOS提供時鐘節拍做時間基準。基本定時器
    發表于 11-23 18:21 ?19次下載
    STM32基于cubeMX<b class='flag-5'>實現</b><b class='flag-5'>定時器</b>點燈

    STM32定時器-基本定時器

    目錄定時器分類基本定時器功能框圖講解基本定時器功能時鐘源計數時鐘計數自動重裝載寄存
    發表于 11-23 18:21 ?31次下載
    STM32<b class='flag-5'>定時器</b>-基本<b class='flag-5'>定時器</b>

    STM32——高級定時器、通用定時器、基本定時器的區別

    STM32——高級定時器、通用定時器、基本定時器的區別
    發表于 11-26 15:21 ?110次下載
    STM32——高級<b class='flag-5'>定時器</b>、通用<b class='flag-5'>定時器</b>、基本<b class='flag-5'>定時器</b>的區別

    SysTick 定時器

    的SysTick定時器實現延時,可以不占用系統定時器,節約資源。由于SysTick是在CPU核內部實現的,跟MCU外設無關,因此它的代碼可以在不同廠家之間移植。本 章 將 使用系統滴
    發表于 12-05 14:51 ?9次下載
    SysTick <b class='flag-5'>定時器</b>

    定時器作用實現定時器數據結構選取介紹1

    定時器在各種場景都需要用到,比如游戲的Buff實現,Redis中的過期任務,Linux中的定時任務等等。顧名思義,定時器的主要用途是執行定時
    的頭像 發表于 04-21 15:20 ?1245次閱讀
    <b class='flag-5'>定時器</b><b class='flag-5'>作用</b>及<b class='flag-5'>實現</b><b class='flag-5'>定時器</b><b class='flag-5'>數據結構</b><b class='flag-5'>選取</b><b class='flag-5'>介紹</b>1

    什么是軟件定時器?軟件定時器實現原理

    軟件定時器是用程序模擬出來的定時器,可以由一個硬件定時器模擬出成千上萬個軟件定時器,這樣程序在需要使用較多定時器的時候就不會受限于硬件資源的
    的頭像 發表于 05-23 17:05 ?2890次閱讀

    定時器設計實現

    返回ITimer類型的共享指針。其中ITimer類中定義了start和stop方法,用于啟動或停止當前定時器。 TimerManager還有一個內部類TimerMessageQueue用于實現
    的頭像 發表于 11-08 16:50 ?644次閱讀

    定時器實現數據結構選擇

    在后端的開發中,定時器有很廣泛的應用。 比如: 心跳檢測 倒計時 游戲開發的技能冷卻 redis的鍵值的有效期等等,都會使用到定時器定時器實現
    的頭像 發表于 11-13 14:22 ?561次閱讀
    <b class='flag-5'>定時器</b>的<b class='flag-5'>實現</b><b class='flag-5'>數據結構</b>選擇
    主站蜘蛛池模板: 男人女人边摸边吃奶边做| 久久精品视频在线看99| 久久精品国产色蜜蜜麻豆国语版| 少妇系列之白嫩人妻| 超熟女专门志| 秋霞最新高清无码鲁丝片| a亚洲在线观看不卡高清| 蜜臀久久99精品久久久久久做爰| 在线观看永久免费网址| 久久91精品久久久久久水蜜桃| 亚洲精品www久久久久久久软件| 国产成人一区免费观看| 少妇无套内谢久久久久| 国产精品69人妻无码久久| 谁有成人网站地址| 国产精品无需播放器| 亚洲 欧美 综合 高清 在线| 国产午夜婷婷精品无码A片| 亚洲国产成人私人影院| 精品国产三级a| 中文字幕完整高清版| 免费精品国产日韩热久久| av淘宝 在线观看| 日本无码色哟哟婷婷最新网站| 岛国片在线看| 亚洲成人黄色片| 久爱在线中文在观看| 2020亚洲 欧美 国产 日韩| 免费人成视频19674不收费| xxxxx俄罗斯| 脱女学小内内摸出水网站免费| 国产欧洲野花A级| 伊人青青草原| 欧美在线视频一区| 国产精品成人免费视频99| 亚洲精品电影天堂网| 美女穿丝袜被狂躁动态图| 赤兔CHINESE最新男18GUY| 亚洲精品久久7777777| 免费乱理伦片在线观看夜| 国产成人无码AV麻豆|