就如libevent官网上所写的“libevent - an event notification library”,libevent就是一个基于事件通知机制的库,可以看出event是整个库的核心。event就是Reactor框架中的事件处理程序组件(event_handler),它提供了函数接口,供Reactor在事件发生时调用,以执行相应的事件处理,通常它会绑定一个有效的句柄。
event结构体定义在<event2/event_struct.h>中:
1 struct event { 2 TAILQ_ENTRY(event) ev_active_next; 3 TAILQ_ENTRY(event) ev_next; 4 /* for managing timeouts */ 5 union { 6 TAILQ_ENTRY(event) ev_next_with_common_timeout; 7 int min_heap_idx; 8 } ev_timeout_pos; 9 evutil_socket_t ev_fd; 10 11 struct event_base *ev_base; 12 13 union { // I/O事件和信号事件不能同时设置 14 /* used for io events */ 15 struct { 16 TAILQ_ENTRY(event) ev_io_next; 17 struct timeval ev_timeout; 18 } ev_io; 19 20 /* used by signal events */ 21 struct { 22 TAILQ_ENTRY(event) ev_signal_next; 23 short ev_ncalls; 24 /* Allows deletes in callback */ 25 short *ev_pncalls; 26 } ev_signal; 27 } _ev; 28 29 short ev_events; 30 short ev_res; /* result passed to event callback */ 31 short ev_flags; 32 ev_uint8_t ev_pri; /* smaller numbers are higher priority */ 33 ev_uint8_t ev_closure; 34 struct timeval ev_timeout; 35 36 /* allows us to adopt for different types of events */ 37 void (*ev_callback)(evutil_socket_t, short, void *arg); 38 void *ev_arg; 39 };
在原文档中,作者对event结构体做了详细的解释(英文):
/** * @struct event * * Structure to represent a single event. * * An event can have some underlying condition it represents: a socket * becoming readable or writeable (or both), or a signal becoming raised. * (An event that represents no underlying condition is still useful: you * can use one to implement a timer, or to communicate between threads.) * * Generally, you can create events with event_new(), then make them * pending with event_add(). As your event_base runs, it will run the * callbacks of an events whose conditions are triggered. When you * longer want the event, free it with event_free(). * * In more depth: * * An event may be "pending" (one whose condition we are watching), * "active" (one whose condition has triggered and whose callback is about * to run), neither, or both. Events come into existence via * event_assign() or event_new(), and are then neither active nor pending. * * To make an event pending, pass it to event_add(). When doing so, you * can also set a timeout for the event. * * Events become active during an event_base_loop() call when either their * condition has triggered, or when their timeout has elapsed. You can * also activate an event manually using event_active(). The even_base * loop will run the callbacks of active events; after it has done so, it * marks them as no longer active. * * You can make an event non-pending by passing it to event_del(). This * also makes the event non-active. * * Events can be "persistent" or "non-persistent". A non-persistent event * becomes non-pending as soon as it is triggered: thus, it only runs at * most once per call to event_add(). A persistent event remains pending * even when it becomes active: you'll need to event_del() it manually in * order to make it non-pending. When a persistent event with a timeout * becomes active, its timeout is reset: this means you can use persistent * events to implement periodic timeouts. * * This should be treated as an opaque structure; you should never read or * write any of its fields directly. For backward compatibility with old * code, it is defined in the event2/event_struct.h header; including this * header may make your code incompatible with other versions of Libevent. * * @see event_new(), event_free(), event_assign(), event_get_assignment(), * event_add(), event_del(), event_active(), event_pending(), * event_get_fd(), event_get_base(), event_get_events(), * event_get_callback(), event_get_callback_arg(), * event_priority_set() */