• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0
            譯自http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html
            轉自:http://blog.sina.com.cn/s/blog_56dee71a0100qe76.html

            運行循環

            一旦有了一個已經注冊了某些事件的event_base(關于如何創建和注冊事件請看下一節),就需要讓libevent等待事件并且通知事件的發生。

            接口
            #define EVLOOP_ONCE             0x01
            #define EVLOOP_NONBLOCK         0x02
            #define EVLOOP_NO_EXIT_ON_EMPTY 0x04

            int event_base_loop(struct event_base *baseint flags);

            默認情況下,event_base_loop()函數運行event_base直到其中沒有已經注冊的事件為止。執行循環的時候,函數重復地檢查是否有任何已經注冊的事件被觸發(比如說,讀事件的文件描述符已經就緒,可以讀取了;或者超時事件的超時時間即將到達)。如果有事件被觸發,函數標記被觸發的事件為“激活的”,并且執行這些事件。

            在flags參數中設置一個或者多個標志就可以改變event_base_loop()的行為。如果設置了EVLOOP_ONCE,循環將等待某些事件成為激活的,執行激活的事件直到沒有更多的事件可以執行,然會返回。如果設置了EVLOOP_NONBLOCK,循環不會等待事件被觸發:循環將僅僅檢測是否有事件已經就緒,可以立即觸發,如果有,則執行事件的回調。

            完成工作后,如果正常退出,event_base_loop()返回0;如果因為后端中的某些未處理錯誤而退出,則返回-1。

            為幫助理解,這里給出event_base_loop()的算法概要:

            偽代碼

            while (any events are registered with the loop,
                    or EVLOOP_NO_EXIT_ON_EMPTY was 
            set) {

                
            if (EVLOOP_NONBLOCK was set, or any events are already active)
                    If any registered events have triggered, mark them active.
                
            else
                    Wait until at least one 
            event has triggered, and mark it active.

                
            for (p = 0; p < n_priorities; ++p {
                   
            if (any event with priority of p is active) {
                      Run all active events with priority of p.
                      
            break/* Do not run any events of a less important priority */
                   }
                }

                
            if (EVLOOP_ONCE was set or EVLOOP_NONBLOCK was set)
                   
            break;
            }

            為方便起見,也可以調用

            接口

            int event_base_dispatch(struct event_base *base);

            event_base_dispatch()等同于沒有設置標志的event_base_loop()。所以,event_base_dispatch()將一直運行,直到沒有已經注冊的事件了,或者調用了event_base_loopbreak()或者event_base_loopexit()為止。

            這些函數定義在<event2/event.h>中,從libevent 1.0版就存在了。

            停止循環

            如果想在移除所有已注冊的事件之前停止活動的事件循環,可以調用兩個稍有不同的函數。

            接口

            int event_base_loopexit(struct event_base *base,
                                    
            const struct timeval *tv);
            int event_base_loopbreak(struct event_base *base);

            event_base_loopexit()讓event_base在給定時間之后停止循環。如果tv參數為NULL,event_base會立即停止循環,沒有延時。如果event_base當前正在執行任何激活事件的回調,則回調會繼續運行,直到運行完所有激活事件的回調之才退出。

            event_base_loopbreak()讓event_base立即退出循環。它與event_base_loopexit(base,NULL)的不同在于,如果event_base當前正在執行激活事件的回調,它將在執行完當前正在處理的事件后立即退出。

            注意event_base_loopexit(base,NULL)和event_base_loopbreak(base)在事件循環沒有運行時的行為不同:前者安排下一次事件循環在下一輪回調完成后立即停止(就好像帶EVLOOP_ONCE標志調用一樣);后者卻僅僅停止當前正在運行的循環,如果事件循環沒有運行,則沒有任何效果。

            這兩個函數都在成功時返回0,失敗時返回-1。

            示例:立即關閉

            #include <event2/event.h>

            /* Here's a callback function that calls loopbreak */
            void cb(int sock, short what, void *arg)
            {
                
            struct event_base *base = arg;
                event_base_loopbreak(
            base);
            }

            void main_loop(struct event_base *base, evutil_socket_t watchdog_fd)
            {
                
            struct event *watchdog_event;

                
            /* Construct a new event to trigger whenever there are any bytes to
                   read from a watchdog socket.  When that happens, we'll call the
                   cb function, which will make the loop exit immediately without
                   running any other active events at all.
                 
            */
                watchdog_event 
            = event_new(base, watchdog_fd, EV_READ, cb, base);

                event_add(watchdog_event, NULL);

                event_base_dispatch(
            base);
            }

            示例:執行事件循環10秒,然后退出

            #include <event2/event.h>

            void run_base_with_ticks(struct event_base *base)
            {
              
            struct timeval ten_sec;

              ten_sec.tv_sec 
            = 10;
              ten_sec.tv_usec 
            = 0;

              
            /* Now we run the event_base for a series of 10-second intervals, printing
                 "Tick" after each.  For a much better way to implement a 10-second
                 timer, see the section below about persistent timer events. 
            */
              
            while (1) {
                 
            /* This schedules an exit ten seconds from now. */
                 event_base_loopexit(
            base&ten_sec);

                 event_base_dispatch(
            base);
                 puts(
            "Tick");
              }
            }

            有時候需要知道對event_base_dispatch()或者event_base_loop()的調用是正常退出的,還是因為調用event_base_loopexit()或者event_base_break()而退出的。可以調用下述函數來確定是否調用了loopexit或者break函數。

            接口

            int event_base_got_exit(struct event_base *base);
            int event_base_got_break(struct event_base *base);

            這兩個函數分別會在循環是因為調用event_base_loopexit()或者event_base_break()而退出的時候返回true,否則返回false。下次啟動事件循環的時候,這些值會被重設。

            這些函數聲明在<event2/event.h>中。event_break_loopexit()函數首次在libevent 1.0c版本中實現;event_break_loopbreak()首次在libevent 1.4.3版本中實現。

            檢查內部時間緩存

            有時候需要在事件回調中獲取當前時間的近似視圖,但不想調用gettimeofday()(可能是因為OS將gettimeofday()作為系統調用實現,而你試圖避免系統調用的開銷)。

            在回調中,可以請求libevent開始本輪回調時的當前時間視圖。

            接口

            int event_base_gettimeofday_cached(struct event_base *base,
                
            struct timeval *tv_out);

            如果當前正在執行回調,event_base_gettimeofday_cached()函數設置tv_out參數的值為緩存的時間。否則,函數調用evutil_gettimeofday()獲取真正的當前時間。成功時函數返回0,失敗時返回負數。

            注意,因為libevent在開始執行回調的時候緩存時間值,所以這個值至少是有一點不精確的。如果回調執行很長時間,這個值將非常不精確。

            這個函數是libevent 2.0.4-alpha新引入的。

            轉儲event_base的狀態

            接口

            void event_base_dump_events(struct event_base *base, FILE *f);

            為幫助調試程序(或者調試libevent),有時候可能需要加入到event_base的事件及其狀態的完整列表。調用event_base_dump_events()可以將這個列表輸出到指定的文件中。

            這個列表是人可讀的,未來版本的libevent將會改變其格式。

            這個函數在libevent 2.0.1-alpha版本中引入。

            廢棄的事件循環函數

            前面已經討論過,老版本的libevent 具有“當前”event_base的概念。

            本文討論的某些事件循環函數具有操作當前event_base的變體。除了沒有base參數外,這些函數跟當前新版本函數的行為相同。

            注意

            2.0版本之前的event_base是不支持鎖的,所以這些函數并不是完全線程安全的:不允許在執行事件循環的線程之外的其他線程中調用_loopbreak()或者_loopexit()函數。

            99久久做夜夜爱天天做精品| 久久久久综合网久久| 久久久久婷婷| 久久精品国产AV一区二区三区| 伊人久久无码中文字幕| 欧美一区二区精品久久| 久久影视综合亚洲| 久久天天躁狠狠躁夜夜躁2O2O| 国产精品无码久久综合网| 精品一二三区久久aaa片| 国内精品久久久久久不卡影院 | 久久精品国产久精国产思思| 久久精品国产影库免费看| 亚洲精品国产综合久久一线| 狠狠色噜噜狠狠狠狠狠色综合久久 | 久久久久高潮毛片免费全部播放| yellow中文字幕久久网| 久久综合噜噜激激的五月天| 久久久久亚洲av成人无码电影| 91精品国产综合久久精品| 亚洲国产欧美国产综合久久| 国内精品久久久久久久亚洲| 99精品国产在热久久无毒不卡| 亚洲伊人久久精品影院| 亚洲国产精品成人AV无码久久综合影院| 成人妇女免费播放久久久| 久久精品aⅴ无码中文字字幕不卡| 亚洲国产成人精品久久久国产成人一区二区三区综 | a高清免费毛片久久| 三上悠亚久久精品| 中文字幕热久久久久久久| 欧美精品九九99久久在观看| 久久亚洲国产精品123区| 国内精品免费久久影院| 国产99久久久国产精品~~牛| 久久亚洲国产欧洲精品一| 热99re久久国超精品首页| 国产精品青草久久久久福利99 | 久久久久国产视频电影| 久久精品这里只有精99品| 亚洲国产天堂久久综合|