日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

libev源码解析——定时器监视器和组织形式

發(fā)布時間:2023/11/27 生活经验 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 libev源码解析——定时器监视器和组织形式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ? ? 我們先看下定時器監(jiān)視器的數(shù)據(jù)結(jié)構(gòu)。(轉(zhuǎn)載請指明出于breaksoftware的csdn博客)

/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
typedef struct ev_timer
{EV_WATCHER_TIME (ev_timer)ev_tstamp repeat; /* rw */
} ev_timer;/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */
/* revent EV_PERIODIC */
typedef struct ev_periodic
{EV_WATCHER_TIME (ev_periodic)ev_tstamp offset; /* rw */ev_tstamp interval; /* rw */ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_THROW; /* rw */
} ev_periodic;

? ? ? ? ev_timer是相對時間定時器監(jiān)視器,ev_periodic是絕對時間定時器監(jiān)視器。可以注意到,這兩個監(jiān)視器結(jié)構(gòu)開頭都擁有近乎相同的成員變量,即EV_WATCHER_TIME宏中定義的那部分

#define EV_WATCHER_TIME(type)			\EV_WATCHER (type)				\ev_tstamp at;     /* private */

? ? ? ? 為什么說“近乎相同”,是因為它們傳遞給EV_WATCHER宏的參數(shù)不同,而從會導(dǎo)致各自擁有一個名稱不同的回調(diào)函數(shù)指針,而其他變量連名稱都一樣。

? ? ? ? 對這兩種監(jiān)視器,libev并沒有像《libev源碼解析——監(jiān)視器(watcher)結(jié)構(gòu)和組織形式》文中所述,將這些監(jiān)視器關(guān)聯(lián)到文件描述符作為下標(biāo)的anfds結(jié)構(gòu)中。

? ? ? ? 為什么不放在上述結(jié)構(gòu)中?因為保存到anfds中的監(jiān)視器,都是要求文件描述符對應(yīng)的事件發(fā)生而被觸發(fā)。而定時器是要求文件描述符對應(yīng)的事件沒有發(fā)生,通過等待超時而被觸發(fā)(或者被其他無關(guān)事件觸發(fā),順帶執(zhí)行)。所以將定時器監(jiān)視器保存在這個結(jié)構(gòu)中是沒有用的。同時這也意味著,向pendings結(jié)構(gòu)(《libev源碼解析——調(diào)度策略》)中記錄本次觸發(fā)的監(jiān)視器的數(shù)據(jù)來源并非只有anfds,還有定時器監(jiān)視器相關(guān)的結(jié)構(gòu)。

? ? ? ? 那這個結(jié)構(gòu)是什么呢?我們先看下基礎(chǔ)結(jié)構(gòu)定義

  /* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_time
{EV_WATCHER_TIME (ev_watcher_time)
} ev_watcher_time;typedef ev_watcher_time *WT;typedef struct {ev_tstamp at;WT w;
} ANHE;

? ? ? ? ev_watcher_timer和ev_timer、ev_periodic有著近乎一致的數(shù)據(jù)格式——它們都是使用EV_WATCHER_TIME宏構(gòu)成開始的幾個成員變量。

? ? ? ? 這意味著,在忽略回調(diào)函數(shù)名的情況下,我們可以使用ev_watcher_timer指針指向ev_timer結(jié)構(gòu)體對象或者ev_periodic結(jié)構(gòu)體對象。

? ? ? ? 因為ANHE結(jié)構(gòu)中變量w可以指向ev_timer,那么目前我們有兩種保存定時器監(jiān)視器的方式(以ev_timer為例):

  1. 連續(xù)的ev_timer結(jié)構(gòu)體對象構(gòu)成的數(shù)組
  2. 連續(xù)的ANHE結(jié)構(gòu)對象構(gòu)成的數(shù)組

? ? ? ? 這兩種結(jié)構(gòu)在內(nèi)存中的布局如下:

? ? ? ? 這兩種結(jié)構(gòu)都有自己的優(yōu)缺點:

  1. 結(jié)構(gòu)比較簡單,各個監(jiān)視器的位置關(guān)系由數(shù)組下標(biāo)維護(hù)。其缺點調(diào)整監(jiān)視器位置比較低效,因為這意味著比較多的內(nèi)存需要被轉(zhuǎn)移。
  2. 結(jié)構(gòu)則相對復(fù)雜,因為其通過一個額外ANHE數(shù)組維護(hù)各個監(jiān)視器的關(guān)系。但是它可以方便的調(diào)整監(jiān)視器的位置——只要調(diào)整各個指針即可。

? ? ? ? 對于結(jié)構(gòu)的選擇,應(yīng)該依據(jù)應(yīng)用場景決定。我們在《libev源碼解析——定時器原理》中提到,libev需要尋找到“下次執(zhí)行時間”離現(xiàn)在最近的監(jiān)視器。如果采用連續(xù)的ev_timer結(jié)構(gòu)存儲,則可以分為如下兩種處理方式:

  • ev_timer數(shù)組中各個元素位置不變,只是修改“下次執(zhí)行時間”。對于這樣亂序的數(shù)組,只有遍歷的辦法才能找到最近的。然而這種方式效率很低。
  • ev_timer數(shù)組中各個元素位置可變。這樣在修改“下次執(zhí)行時間”后,就需要對數(shù)組元素重新布局。

? ? ? ? 而如果采用連續(xù)的ANHE結(jié)構(gòu)存儲,則對于元素位置發(fā)生變化的場景,只要修改兩個字段即可,而不用像上面方案那樣要修改七個字段。相比較而言,這個方案更優(yōu)。libev選用的就是這個方案。

void noinline
ev_timer_start (EV_P_ ev_timer *w) EV_THROW
{
……++timercnt;ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);ANHE_w (timers [ev_active (w)]) = (WT)w;ANHE_at_cache (timers [ev_active (w)]);
……
}

? ? ? ? timers是保存“相對時間定時器”監(jiān)視器的數(shù)組結(jié)構(gòu)。在ev_periodic_start代碼中,我們可以看到“絕對時間定時器”監(jiān)視器保存在名字叫periodics的數(shù)組中。

? ? ? ? 下一步我們就需要尋找一種相對高效的排序算法。首先我們想到的是順序排序,而且離現(xiàn)在時間最近的元素排在數(shù)組第一位。為了方便描述,我們之后將時間改成整數(shù)表示。假設(shè)我們有如下的監(jiān)視器:1、3、5、7、9、11、13。如果時間為1的監(jiān)視器執(zhí)行了,則將其時間差改成12,則數(shù)組的移動方式如下


? ? ? ? w2~w6可以見得,“牽一發(fā)而動全身”。那是否有更好的方式?libev采用的是最小堆。關(guān)于最小堆操作的示例,可以參見《最小堆 構(gòu)建、插入、刪除的過程圖解》。以上例,則操作如下圖

? ? ? ?可見,我們將操作元素的次數(shù)降低到3次,比順序排列的方案要少很多。

? ? ? ?這種操作是自上而下的,對應(yīng)的代碼是

inline_speed void
downheap (ANHE *heap, int N, int k)
{ANHE he = heap [k];for (;;){int c = k << 1;if (c >= N + HEAP0)break;c += c + 1 < N + HEAP0 && ANHE_at (heap [c]) > ANHE_at (heap [c + 1])? 1 : 0;if (ANHE_at (he) <= ANHE_at (heap [c]))break;heap [k] = heap [c];ev_active (ANHE_w (heap [k])) = k;k = c;}heap [k] = he;ev_active (ANHE_w (he)) = k;
}

? ? ? ? 這個行為發(fā)生在定時器監(jiān)視器向pendings結(jié)構(gòu)中記錄時,因為離當(dāng)前時間最近的監(jiān)視器馬上要執(zhí)行,所以要修改它下一次執(zhí)行的時間,然后重新布局結(jié)構(gòu)。

inline_size void
timers_reify (EV_P)
{EV_FREQUENT_CHECK;if (timercnt && ANHE_at (timers [HEAP0]) < mn_now){do{ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]);/*assert (("libev: inactive timer on timer heap detected", ev_is_active (w)));*//* first reschedule or stop timer */if (w->repeat){ev_at (w) += w->repeat;if (ev_at (w) < mn_now)ev_at (w) = mn_now;assert (("libev: negative ev_timer repeat value found while processing timers", w->repeat > 0.));ANHE_at_cache (timers [HEAP0]);downheap (timers, timercnt, HEAP0);

? ? ? ? 還有一種是自下而上的重新布局,這種發(fā)生在新增一個定時器時。


? ? ? ? 相應(yīng)代碼是

inline_speed void
upheap (ANHE *heap, int k)
{ANHE he = heap [k];for (;;){int p = HPARENT (k);if (UPHEAP_DONE (p, k) || ANHE_at (heap [p]) <= ANHE_at (he))break;heap [k] = heap [p];ev_active (ANHE_w (heap [k])) = k;k = p;}heap [k] = he;ev_active (ANHE_w (he)) = k;
}
void noinline
ev_timer_start (EV_P_ ev_timer *w) EV_THROW
{if (expect_false (ev_is_active (w)))return;ev_at (w) += mn_now;assert (("libev: ev_timer_start called with negative timer repeat value", w->repeat >= 0.));EV_FREQUENT_CHECK;++timercnt;ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1);array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2);ANHE_w (timers [ev_active (w)]) = (WT)w;ANHE_at_cache (timers [ev_active (w)]);upheap (timers, ev_active (w));EV_FREQUENT_CHECK;/*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/
}

? ? ? ? 至此,《libev源碼解析》系列已經(jīng)講完。經(jīng)過這個系列分析,我們應(yīng)該可以對libev整體實現(xiàn)原理和關(guān)鍵結(jié)構(gòu)有了充分的了解。

? ? ? ? 至于具體實現(xiàn),可以參見《libev中文手冊》。

?

總結(jié)

以上是生活随笔為你收集整理的libev源码解析——定时器监视器和组织形式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。