99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

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

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

3天內(nèi)不再提示

定時器作用及實現(xiàn)定時器數(shù)據(jù)結(jié)構(gòu)選取介紹2

jf_78858299 ? 來源:程序員不是碼農(nóng) ? 作者:程序員不是碼農(nóng) ? 2023-04-21 15:20 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Skynet定時器實現(xiàn)方案

skynet中定時器數(shù)據(jù)結(jié)構(gòu)

采用時間輪方式,hash表+鏈表實現(xiàn),

struct timer_node {  //時間節(jié)點
 struct timer_node *next;
    uint32_t expire; //到期滴答數(shù)
};
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;  // 記錄當前滴答數(shù)
    uint64_t starttime;
    uint64_t current;
    uint64_t current_point;
};

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

定時器執(zhí)行流程

圖片

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

以下為具體實現(xiàn),僅貼出主要接口,具體細節(jié)請參考skynet源代碼。

定時器初始化
// skynet_start.c
// skynet 啟動入口
void
skynet_start(struct skynet_config * config) {
    ...
    skynet_timer_init();
    ...
}
// skynet_timer.c
void
skynet_timer_init(void) {
    // 創(chuàng)建全局timer結(jié)構(gòu) 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調(diào)用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;
    // 添加新的定時器節(jié)點
    timer_add(TI, &event, sizeof(event), time);
    return session;
}
// 添加新的定時器節(jié)點
static void timer_add(struct timer *T, void 8arg, size_t sz, int time) {
    // 給timer_node指針分配空間,還需要分配timer_node + timer_event大小的空間,
    // 之后通過node + 1可獲得timer_event數(shù)據(jù)
    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);
}

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

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

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

每個定時器設置一個到期滴答數(shù),與當前系統(tǒng)的滴答數(shù)(啟動時為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中觸發(fā)到期得定時器
static inline void
timer_execute(struct timer *T) {
  ...
}
// 遍歷處理定時器鏈表中所有的定時器
static inline void
dispatch_list(struct timer_node *current) {
    ...
}
// 將高24位對應的4個6位的數(shù)組中的各個元素的鏈表往低位移
static void
timer_shift(struct timer *T) {
    ...
}
// 將level層的idx位置的定時器鏈表從當前位置刪除,并重新add_node
static void move_list(struct timer *T, int level, int idx) {

}

最小堆實現(xiàn)定時器

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

具體實現(xiàn)略。

總結(jié)

本文主要介紹定時器作用,實現(xiàn)定時器數(shù)據(jù)結(jié)構(gòu)選取,并詳細介紹了跳表,紅黑樹,時間輪實現(xiàn)定時器的思路和方法。

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

公眾號

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    定時器/計數(shù)基礎

    15-1.實現(xiàn)定時的方法15-2.定時器/計數(shù)結(jié)構(gòu)和工作原理 15-3.
    發(fā)表于 03-23 12:17 ?48次下載

    555定時器

    555定時器555定時器555定時器555定時器555定時器555定時器555
    發(fā)表于 11-10 17:25 ?54次下載

    基于51單片機的定時器2的操作與實現(xiàn)

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

    定時器介紹

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

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

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

    STC51定時器定時器中斷

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

    stm32—定時器配置

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

    STM32基于cubeMX實現(xiàn)定時器點燈

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

    STM32定時器-基本定時器

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

    STM32——高級定時器、通用定時器、基本定時器的區(qū)別

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

    SysTick 定時器

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

    定時器作用實現(xiàn)定時器數(shù)據(jù)結(jié)構(gòu)選取介紹1

    定時器在各種場景都需要用到,比如游戲的Buff實現(xiàn),Redis中的過期任務,Linux中的定時任務等等。顧名思義,定時器的主要用途是執(zhí)行定時
    的頭像 發(fā)表于 04-21 15:20 ?1597次閱讀
    <b class='flag-5'>定時器</b><b class='flag-5'>作用</b>及<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>定時器</b><b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b><b class='flag-5'>選取</b><b class='flag-5'>介紹</b>1

    什么是軟件定時器?軟件定時器實現(xiàn)原理

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

    定時器設計實現(xiàn)

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

    定時器實現(xiàn)數(shù)據(jù)結(jié)構(gòu)選擇

    在后端的開發(fā)中,定時器有很廣泛的應用。 比如: 心跳檢測 倒計時 游戲開發(fā)的技能冷卻 redis的鍵值的有效期等等,都會使用到定時器定時器實現(xiàn)
    的頭像 發(fā)表于 11-13 14:22 ?729次閱讀
    <b class='flag-5'>定時器</b>的<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>選擇