libevent原始碼淺析: http庫
上一篇文章介紹了libevent下基本的I/O事件,這篇文章將講講libevent對定時器和訊號事件的處理.
Timer事件反應堆event_base包含了一個最小堆min_heap結構體的例項,以此維護註冊到這個反應堆例項的定時器事件:
1.struct event_base
{
2.//其他成員
3.struct min_heap
timeheap;
4.};
回顧一下最小堆min_heap:
1.typedef struct min_heap
2.{
3.//p指向一個動態分配的陣列,陣列元素是event指標.
4.struct event**
p;
5.unsigned
n, a; // n表示目前儲存了多少元素,a表示p指向的記憶體能夠儲存event指標的個數
6.}
min_heap_t;
可以看到,它包含一個連續的記憶體塊用於儲存定時器事件.針對min_heap的操作主要有:
1.static inline int min_heap_push(min_heap_t*
s, struct event* e);
2.static inline struct event*
min_heap_pop(min_heap_t* s);
其中,min_heap_push()用於插入節點,min_heap_pop()用於彈出節點.其內部邏輯很簡單,不必描述了.
現在看看libevent處理定時器事件的例子:
01.static void timeout_cb(int fd, short event, void *arg)
{...}
02.
03.int main
(int argc, char **argv)
04.{
05.struct event
timeout;
06.struct timeval
tv;
07.
08.event_init();
09.
10.evtimer_set(&timeout,
timeout_cb, &timeout);
11.
12.evutil_timerclear(&tv);
13.tv.tv_sec
= 2;
14.event_add(&timeout,
&tv);
15.
16.lasttime
= time(NULL);
17.
18.event_dispatch();
19.}
首先,和上篇文章例子一樣的,event_init()初始化一個event_base(反應堆例項),然後由evtimer_set()設定定時器事件的回撥函式,接著event_add()把定時器事件加入反應堆例項中.最後進入event_dispatch()主迴圈.
在這裡,evtimer_set定義如下:
1.#define
evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg)
至於event_set(),沒有什麼好說的,就是對一個event結構體做初始化罷了.
上一篇文章已經從I/O事件的角度介紹了event_add(),這裡看看它是如何處理定時器事件的:
01.int event_add(struct event
*ev, const struct timeval *tv)
02.{
03.struct event_base
*base = ev->ev_base;
04.
05.....//處理IO事件或者訊號事件的邏輯.
06.
07.//如果tv不為0
08.if (tv
!= NULL)
09.{
10.event_queue_insert(base,
ev, EVLIST_TIMEOUT);
11.}
12.}
可以看到,event_add()會把一個定時器事件壓入到其對應的反應堆例項下的定時器最小堆timeheap中(&ev->base.timeheap).
回到event_dispatch(),它會呼叫event_base_loop(),此函式對定時器事件處理如下:
01.//事件主迴圈
02.int
03.event_base_loop(struct event_base
*base, int flags)
04.{
05....//不必多慮的其他程式碼
06.
07.done
= 0;
08.while (!done)
09.{
10.//檢查heap中的timer
events,將就緒的timer event從heap上刪除,並插入到啟用連結串列中,
11.//這意味著base->event_count_active會增加
12.timeout_process(base);
13.
14.//有就緒事件了
15.if (base->event_count_active)
16.{
17.//處理就緒事件吧.
18.event_process_active(base);
19.}
20.}
21.}
其中,timeout_process()會將已超時的定時器事件插入到反應堆例項下的已就緒事件佇列中,接著由event_process_active()處理已就緒事件.event_process_active()程式碼在上一篇文章中已經介紹過了,這裡看一下timeout_process():
01./時間到~~~
02.//開始處理base裡面的定時器堆裡的事件鳥.
03.//檢查heap中的timer
events,將就緒的timer event從heap上刪除,並插入到啟用連結串列中
04.void timeout_process(struct event_base
*base)
05.{
06.struct timeval
now;
07.struct event
*ev;
08.
09.while ((ev
= min_heap_top(&base->timeheap)))
10.{
11.//ev超時時間的比現在的時間大,也就是說,這個ev還沒有超時,那麼while迴圈結束
12.if (evutil_timercmp(&ev->ev_timeout,
&now, >))
13.break;
14.
15.//else
意味著 evutil_timercmp(&ev->ev_timeout, &now, <=)為真
16.//也就說明定時器最小堆的根超時了
17.
18.//從定時器堆刪除
19.event_del(ev);
20.
21.//把它插到啟用連結串列吧.
22.event_active(ev,
EV_TIMEOUT, 1);
23.}
24.
相關推薦
libevent原始碼淺析: http庫
上一篇文章介紹了libevent下基本的I/O事件,這篇文章將講講libevent對定時器和訊號事件的處理.Timer事件 反應堆event_base包含了一個最小堆min_heap結構體的例項,以此維護註冊到這個反應堆例項的定時器事件:1.struct event_base {2.//其他成員3.struc
小而美的Promise庫——promiz原始碼淺析
背景 在上一篇部落格[[譯]前端基礎知識儲備——Promise/A+規範](https://segmentfault.com/a/11...,我們介紹了Promise/A+規範的具體條目。在本文中,我們來選擇了promiz,讓大家來看下一個具體的Promise庫的內部程式碼是如何運作的。 promiz是一
優秀開源庫SDWebImage原始碼淺析
世人都說閱讀原始碼對於功力的提升是十分顯著的, 但是很多的著名開源框架原始碼動輒上萬行, 複雜度實在太高, 這裡只做基礎的分析。 簡潔的介面 首先來介紹一下這個 SDWebImage 這個著名開源框架吧, 這個開源框架的主要作用就是: Asynchronous image downloader w
Python HTTP庫requests中文頁面亂碼解決方案!
獲得 使用 http text odin 抽取 from Coding blog 把html編碼類型賦與獲取到文本 獲取html編碼類型: 1.使用apparent_encoding可以獲得真實編碼 1 >>> response.apparent_enc
淺析muduo庫中的定時器設施
val read eid 就是 RR 重新 cal using dss 一個設計良好的定時器在服務端的應用程序上至關重要,muduo定時器的實現陳碩大牛在書中已經詳細的談過,筆者嘗試從源碼的角度解讀定時器的實現,如果理解不對,歡迎指正。 在muduo的定時器系統中,一共由四
淺析muduo庫中的線程設施
%d except a* empty fde returns exceptio HR 參數傳遞 muduo是目前我在學習過程中遇到的最具有學習意義的網絡庫,下文將分析muduo庫中的基礎設施--Thread和ThreadPool. 首先,介紹在多線程編程中不可缺少的同步措施
Axios 是一個基於 promise 的 HTTP 庫
else eve stringify http UNC bracket mil validate white NPM地址:https://www.npmjs.com/package/axios安裝使用 npm:$ npm install axios使用 bower:$ bo
用最簡單的方式實現基於libevent框架的http client客戶端
#include <event2/event_struct.h> #include <event2/event.h> #include <event2/bufferevent.h> #include <event2/http.h> #include
基於libevent框架搭建http伺服器
#include <stdlib.h> #include <stdio.h> #include <string.h> //libevent http server header files #include <event2/http.h> #in
重新去認識HashMap(Java8原始碼淺析)
加入新公司後一直忙於專案,瘋狂加班,斷更了N個月,一直沒時間去管理自己所學習的新的知識(說白了就是懶。。。),前些天在頭條上看到了一篇關於jdk5,6,7,8,9的一些區別的文章,雖然有所瞭解,但由於自己的專案中用的依舊還是1.6,因此並沒有很多機會去了解一些新版本的一些特性(說白了還是
Android Hook框架adbi原始碼淺析(二)
二、libbase 其實上面載入完SO庫後,hook的功能我們完全可以自己在動態庫中實現。而adbi作者為了方便我們使用,編寫了一個通用的hook框架工具即libbase庫。libbase依然在解決兩個問題:1.獲取要hook的目標函式地址;2.給函式打二進位制補丁即inline hook。 關於獲取ho
Android Hook框架adbi原始碼淺析(一)
adbi(The Android Dynamic Binary Instrumentation Toolkit)是一個Android平臺通用hook框架,基於動態庫注入與inline hook技術實現。該框架由兩個主要模組構成,1.hijack負責將動態庫注入到目標程序;2.libbase提供動態庫本身,它實
c++常用原始碼以及常用庫查詢
我平時看程式碼主要是C和C++程式碼為主,Java程式碼也會偶爾看一下。平時除了自己積累一些程式碼之外,也會主動去尋找一些程式碼,比如說, (1)到sourceforge上查詢相關程式碼; (2)到google code上面查詢具體的程式碼; (3)到apache網站上尋找ja
攝像頭程式設計大全 原始碼 c http //tmsoft lsxy com/index php load read i
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
linux kernel(二)原始碼淺析
目錄 kernel(二)原始碼淺析 建立工程 啟動簡析 head.s 入口點 查詢處理器 查詢機器ID 啟動MMU 其他操作 start_kernel 處理命令列
FileProvider使用以及原始碼淺析
1. FileProvider的使用 1.1 AndroidManifest.xml中定義 <provider android:name="android.support.v4.content.FileProvider" a
[JDK1.7]LinkedHashMap原始碼淺析
引言 HashMap 是一個無序的 Map,因為每次根據 key 的 hashcode 對映到 Entry 陣列上,所以遍歷出來的順序並不是寫入的順序。LinkedHashMap 的底層是繼承於 HashMap 實現的,由一個雙向連結串列所構成; 一、初識LinkedH
libevent學習之一:libevent原始碼的特點和結構
1.特點 Libevent是一個用於開發可擴充套件性網路伺服器的基於事件驅動(event-driven)模型的網路庫。Libevent有幾個顯著的特點: (1)事件驅動(event-driven),高效能; (2)輕量級,專注於網路,不如 ACE 那麼臃腫龐大; (3)原始碼
Django-Rest-Framework 許可權管理原始碼淺析
許可權管理簡單介紹 在django的views中不論是用類方式還是用裝飾器方式來使用rest框架,django_rest_frame實現許可權管理都需要兩個東西的配合:authentication_classes 和 permission_classes # 方式1: 裝飾器 from rest_fram
併發程式設計:LinkedBlockingQueue原始碼淺析
申明:本文是基於jdk1.8的原始碼 LinkedBlockingQueue類圖結構 LinkedBlockingQueue底層基於單向連結串列實現的阻塞佇列,可以當做無界佇列也可以當做有界佇列來使用。 為什麼可以當做無界佇列? 從第一個無參構造方法可知,在沒有