libevent (hello-world代码源码)----event_base

目录

event.h 

event_base

event_base_new

event_base_free

eventbase_loop

event_base_dispatch

event_base_new_with_config

eventop

event_changelist

event_change

evsig_info

TAILQ_HEAD

evcallback_list

event_callback

common_timeout_list

event_signal_map

event_base_config_flag

event-internal.h


这是libevent helloworld的代码:

​
int
main(int argc, char **argv)
{
	struct event_base *base;
	struct evconnlistener *listener;
	struct event *signal_event;

	struct sockaddr_in sin;
#ifdef _WIN32
	WSADATA wsa_data;
	WSAStartup(0x0201, &wsa_data);
#endif

	base = event_base_new();
	if (!base) {
		fprintf(stderr, "Could not initialize libevent!\n");
		return 1;
	}

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);

	listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
	    LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
	    (struct sockaddr*)&sin,
	    sizeof(sin));

	if (!listener) {
		fprintf(stderr, "Could not create a listener!\n");
		return 1;
	}

	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);

	if (!signal_event || event_add(signal_event, NULL)<0) {
		fprintf(stderr, "Could not create/add a signal event!\n");
		return 1;
	}

	event_base_dispatch(base);

	evconnlistener_free(listener);
	event_free(signal_event);
	event_base_free(base);

	printf("done\n");
	return 0;
}

​

现在,让我们看代码的第一行:

struct event_base *base;

 先简单看一下event_base及其相关的定义。

event.h 

event_base

/**
 * Structure to hold information and state for a Libevent dispatch loop.
 *
 * The event_base lies at the center of Libevent; every application will
 * have one.  It keeps track of all pending and active events, and
 * notifies your application of the active ones.
 *
 * This is an opaque structure; you can allocate one using
 * event_base_new() or event_base_new_with_config().
 *
 * @see event_base_new(), event_base_free(), event_base_loop(),
 *    event_base_new_with_config()
 */

struct event_base

结构来保存Libevent调度循环的信息和状态。
event_ base位于Libevent的中心;每个应用程序都有一个。它跟踪所有挂起和活动事件,并将活动事件通知应用程序。
这是一个不透明的结构;您可以使用event_ base_new()或event_base_new_with_config()。
 

event_base_new

/**
 * Create and return a new event_base to use with the rest of Libevent.
 *
 * @return a new event_base on success, or NULL on failure.
 *
 * @see event_base_free(), event_base_new_with_config()
 */
EVENT2_EXPORT_SYMBOL
struct event_base *event_base_new(void);


创建并返回一个新的event_base,以与libevent的其余部分一起使用。
根据成功返回一个新事件_ base,或根据失败返回NULL。
请参阅event_base_free()、event_ base_new_with_config()

event_base_free

/**
  Deallocate all memory associated with an event_base, and free the base.

  Note that this function will not close any fds or free any memory passed
  to event_new as the argument to callback.

  If there are any pending finalizer callbacks, this function will invoke
  them.

  @param eb an event_base to be freed
 */
EVENT2_EXPORT_SYMBOL
void event_base_free(struct event_base *);

释放与event_ base关联的所有内存,并释放该base。请注意,此函数不会关闭任何FD或释放任何传递的内存将event_ new作为回调的参数。如果有任何挂起的终结器回调,此函数将调用他们
 

eventbase_loop

/**
  Wait for events to become active, and run their callbacks.

  This is a more flexible version of event_base_dispatch().

  By default, this loop will run the event base until either there are no more
  pending or active events, or until something calls event_base_loopbreak() or
  event_base_loopexit().  You can override this behavior with the 'flags'
  argument.

  @param eb the event_base structure returned by event_base_new() or
     event_base_new_with_config()
  @param flags any combination of EVLOOP_ONCE | EVLOOP_NONBLOCK
  @return 0 if successful, -1 if an error occurred, or 1 if we exited because
     no events were pending or active.
  @see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE,
     EVLOOP_NONBLOCK
  */
EVENT2_EXPORT_SYMBOL
int event_base_loop(struct event_base *, int);

等待事件变为活动状态,然后运行它们的回调。这是event_base_dispatch()的更灵活版本。默认情况下,此循环将运行事件库,直到没有更多事件挂起或活动事件,或直到有东西调event_base_loopbreak()或event_base_loopexit()。您可以使用“标志”覆盖此行为争论。

event_base_dispatch

/**
   Event dispatching loop

  This loop will run the event base until either there are no more pending or
  active, or until something calls event_base_loopbreak() or
  event_base_loopexit().

  @param base the event_base structure returned by event_base_new() or
     event_base_new_with_config()
  @return 0 if successful, -1 if an error occurred, or 1 if we exited because
     no events were pending or active.
  @see event_base_loop()
 */
EVENT2_EXPORT_SYMBOL
int event_base_dispatch(struct event_base *);

此循环将运行事件库,直到没有更多挂起或或直到有东西调用event_base_loopbreak()或event_base_loopexit()。

event_base_new_with_config

/**
  Initialize the event API.

  Use event_base_new_with_config() to initialize a new event base, taking
  the specified configuration under consideration.  The configuration object
  can currently be used to avoid certain event notification mechanisms.

  @param cfg the event configuration object
  @return an initialized event_base that can be used to registering events,
     or NULL if no event base can be created with the requested event_config.
  @see event_base_new(), event_base_free(), event_init(), event_assign()
*/
EVENT2_EXPORT_SYMBOL
struct event_base *event_base_new_with_config(const struct event_config *);

初始化事件API。
使用event_base_new_with_config()初始化新的事件库,同时考虑指定的配置。配置对象当前可用于避免某些事件通知机制。

eventop

/** Structure to define the backend of a given event_base. */

定义给定event_ base的后端的结构

event_changelist

/* List of 'changes' since the last call to eventop.dispatch.  Only maintained
 * if the backend is using changesets. */
struct event_changelist {
    struct event_change *changes;
    int n_changes;
    int changes_size;
};//自上次调用eventop.dispatch以来的“更改”列表。仅在后端使用变更集时维护。

event_change

/** Represents a */
struct event_change {
    /** The fd or signal whose events are to be changed */
    evutil_socket_t fd;//其事件将被改变的fd或信号
    /* The events that were enabled on the fd before any of these changes
       were made.  May include EV_READ or EV_WRITE. */
    short old_events;//在进行这些更改之前在fd上启用的事件。

    /* The changes that we want to make in reading and writing on this fd.
     * If this is a signal, then read_change has EV_CHANGE_SIGNAL set,
     * and write_change is unused. */
    ev_uint8_t read_change;
    ev_uint8_t write_change;
    ev_uint8_t close_change;
};

evsig_info

/* Data structure for the default signal-handling implementation in signal.c

signal.c中默认信号处理实现的数据结构
 */
struct evsig_info {
    /* Event watching ev_signal_pair[1] */
    struct event ev_signal;
    /* Socketpair used to send notifications from the signal handler */
    evutil_socket_t ev_signal_pair[2];
    /* True iff we've added the ev_signal event yet. */
    int ev_signal_added;
    /* Count of the number of signals we're currently watching. */
    int ev_n_signals_added;

    /* Array of previous signal handler objects before Libevent started
     * messing with them.  Used to restore old signal handlers. */
#ifdef EVENT__HAVE_SIGACTION
    struct sigaction **sh_old;
#else
    ev_sighandler_t **sh_old;
#endif
    /* Size of sh_old. */
    int sh_old_max;
};

TAILQ_HEAD

#define TAILQ_HEAD(name, type)            \
struct name {                    \
    struct type *tqh_first;            \
    struct type **tqh_last;            \
}

evcallback_list

TAILQ_HEAD(evcallback_list, event_callback);

event_callback

struct event_callback {
    TAILQ_ENTRY(event_callback) evcb_active_next;
    short evcb_flags;
    ev_uint8_t evcb_pri;    /* smaller numbers are higher priority */
    ev_uint8_t evcb_closure;
    /* allows us to adopt for different types of events */
        union {
        void (*evcb_callback)(evutil_socket_t, short, void *);
        void (*evcb_selfcb)(struct event_callback *, void *);
        void (*evcb_evfinalize)(struct event *, void *);
        void (*evcb_cbfinalize)(struct event_callback *, void *);
    } evcb_cb_union;
    void *evcb_arg;
};

common_timeout_list

/* A list of events waiting on a given 'common' timeout value.  Ordinarily,
 * events waiting for a timeout wait on a minheap.  Sometimes, however, a
 * queue can be faster.
 **/
struct common_timeout_list {
    /* List of events currently waiting in the queue. */
    struct event_list events;//队列中当前等待的事件列表。
    /* 'magic' timeval used to indicate the duration of events in this
     * queue. */
    struct timeval duration;//“magic”timeval用于指示此队列中事件的持续时间
    /* Event that triggers whenever one of the events in the queue is
     * ready to activate */
    struct event timeout_event;//每当队列中的一个事件准备激活时触发的事件
    /* The event_base that this timeout list is part of */
    struct event_base *base;//此超时列表所属的事件event_base
};

等待给定“公共”超时值的事件列表。通常,等待超时的事件在minheap上等待。然而,有时队列可能更快。

event_signal_map

/* Used to map signal numbers to a list of events.  If EVMAP_USE_HT is not
   defined, this structure is also used as event_io_map, which maps fds to a
   list of events.
*/
struct event_signal_map {
    /* An array of evmap_io * or of evmap_signal *; empty entries are
     * set to NULL. */
    void **entries;
    /* The number of entries available in entries */
    int nentries;
};

用于将信号编号映射到事件列表。如果未定义EVMAP_USE_HT,则此结构也将用作event_io_map,它将FD映射到事件列表。

event_base_config_flag

/**
   A flag passed to event_config_set_flag().

    These flags change the behavior of an allocated event_base.

    @see event_config_set_flag(), event_base_new_with_config(),
       event_method_feature
 */
enum event_base_config_flag {
    /** Do not allocate a lock for the event base, even if we have
        locking set up.

        Setting this option will make it unsafe and nonfunctional to call
        functions on the base concurrently from multiple threads.
//不要为事件库分配锁,即使我们已经设置了锁。设置此选项将使从多个线程同时调用基函数变得不安全和无功能。
    */
    EVENT_BASE_FLAG_NOLOCK = 0x01,
    /** Do not check the EVENT_* environment variables when configuring
        an event_base  */
    EVENT_BASE_FLAG_IGNORE_ENV = 0x02,//配置event_base  时不要检查EVENT_环境变量
    /** Windows only: enable the IOCP dispatcher at startup

        If this flag is set then bufferevent_socket_new() and
        evconn_listener_new() will use IOCP-backed implementations
        instead of the usual select-based one on Windows.
//仅限Windows:在启动时启用IOCP调度程序
如果设置了此标志,则bufferevent_socket_new()和evconn_listener_new()将使用IOCP支持的实现,而不是通常基于Windows的选择实现。
     */
    EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,
    /** Instead of checking the current time every time the event loop is
        ready to run timeout callbacks, check after each timeout callback.
//不是每次事件循环准备运行超时回调时都检查当前时间,而是在每次超时回调后检查。
     */
    EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,

    /** If we are using the epoll backend, this flag says that it is
        safe to use Libevent's internal change-list code to batch up
        adds and deletes in order to try to do as few syscalls as
        possible.  Setting this flag can make your code run faster, but
        it may trigger a Linux bug: it is not safe to use this flag
        if you have any fds cloned by dup() or its variants.  Doing so
        will produce strange and hard-to-diagnose bugs.

        This flag can also be activated by setting the
        EVENT_EPOLL_USE_CHANGELIST environment variable.

        This flag has no effect if you wind up using a backend other than
        epoll.
//如果我们使用的是epoll后端,则此标志表示它是可以安全地使用Libevent的内部更改列表代码进行批处理添加和删除,以便尽可能少地执行系统调用 。设置此标志可以使代码运行更快,但是它可能会触发Linux错误:使用此标志不安全,如果您有任何由dup()或其变体克隆的FD。这样做将产生奇怪且难以诊断的错误。
该标志也可以通过设置EVENT_EPOLL_USE_CHANGELIST是一个环境变量。

如果您最终使用的后端不是epoll,这个设置没用。
     */
    EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,

    /** Ordinarily, Libevent implements its time and timeout code using
        the fastest monotonic timer that we have.  If this flag is set,
        however, we use less efficient more precise timer, assuming one is
        present.
通常,Libevent使用我们现有的最快的单调计时器实现其时间和超时代码。但是,如果设置了此标志,我们将使用效率较低、更精确的计时器,假设存在计时器。
     */
    EVENT_BASE_FLAG_PRECISE_TIMER = 0x20//
};//这些标志更改分配的event_ base的行为。

event-internal.h

struct event_base {
    /** Function pointers and other data to describe this event_base's
     * backend. */
    const struct eventop *evsel;//来描述这个event_ base后端的函数指针和其他数据
    /** Pointer to backend-specific data. */
    void *evbase;//指向后端特定数据的指针。

    /** List of changes to tell backend about at next dispatch.  Only used
     * by the O(1) backends. */
    struct event_changelist changelist;//在下一次调度时告知后端的更改列表。仅由O(1)后端使用。

    /** Function pointers used to describe the backend that this event_base
     * uses for signals */
    const struct eventop *evsigsel;//函数指针,用于描述此event_ base用于信号的后端
    /** Data to implement the common signal handler code. */
    struct evsig_info sig;//用于实现公共信号处理程序代码的数据 TODO 没看懂呢

    /** Number of virtual events */
    int virtual_event_count;//虚拟事件数
    /** Maximum number of virtual events active */
    int virtual_event_count_max;//活动的最大虚拟事件数
    /** Number of total events added to this event_base */
    int event_count;//添加到此event_ base的总事件数
    /** Maximum number of total events added to this event_base */
    int event_count_max;//添加到此event_ base的最大事件总数
    /** Number of total events active in this event_base */
    int event_count_active;//此event_base中活动的总事件数
    /** Maximum number of total events active in this event_base */
    int event_count_active_max;//此event_base中活动的最大事件总数

    /** Set if we should terminate the loop once we're done processing
     * events. */
    int event_gotterm;//设置在处理完事件后是否应终止循环。
    /** Set if we should terminate the loop immediately */
    int event_break;//设置是否应立即终止循环
    /** Set if we should start a new instance of the loop immediately. */
    int event_continue;//设置是否应立即启动循环的新实例

    /** The currently running priority of events */
    int event_running_priority;//事件的当前运行优先级

    /** Set if we're running the event_base_loop function, to prevent
     * reentrant invocation. */
    int running_loop;//如果我们正在运行event_base_loop函数,则设置该参数,以防止重入调用。

    /** Set to the number of deferred_cbs we've made 'active' in the
     * loop.  This is a hack to prevent starvation; it would be smarter
     * to just use event_config_set_max_dispatch_interval's max_callbacks
     * feature */
    int n_deferreds_queued;//设置为我们在循环中“活动”的deferred_cbs 数。这是一种防止饥饿的方法;只使用event_config_set_max_dispatch_interval的max_callbacks特性会更聪明

    /* Active event management. 事件管理*/
    /** An array of nactivequeues queues for active event_callbacks (ones
     * that have triggered, and whose callbacks need to be called).  Low
     * priority numbers are more important, and stall higher ones.
     */
    struct evcallback_list *activequeues;//一组nactivequeues队列,用于活动event_callbacks (已触发且需要调用其回调的回调)。低优先级的数字更重要,而高优先级的数字之后再执行。
    /** The length of the activequeues array */
    int nactivequeues;//activequeues数组的长度
    /** A list of event_callbacks that should become active the next time
     * we process events, but not this time. */
    struct evcallback_list active_later_queue;//event_回调的列表,下次处理事件时应该激活,但这次不会。

    /* common timeout logic */

    /* 公共超时逻辑*/

    /** An array of common_timeout_list* for all of the common timeout
     * values we know. */
    struct common_timeout_list **common_timeout_queues;//一个common_timeout_list*数组,用于我们知道的所有公共超时值。
    /** The number of entries used in common_timeout_queues */
    int n_common_timeouts;//在common_timeout_queues中使用的条目数
    /** The total size of common_timeout_queues. */
    int n_common_timeouts_allocated;//common_timeout_queues 的大小

    /** Mapping from file descriptors to enabled (added) events */
    struct event_io_map io;//从文件描述符到已启用(添加)事件的映射

    /** Mapping from signal numbers to enabled (added) events. */
    struct event_signal_map sigmap;//从信号到启用(添加)事件的映射。

    /** Priority queue of events with timeouts. */
    struct min_heap timeheap;//具有超时的事件的优先级队列。

    /** Stored timeval: used to avoid calling gettimeofday/clock_gettime
     * too often. */
    struct timeval tv_cache;//存储的timeval:用于避免过于频繁地调用gettimeofday/clock_gettime。

    struct evutil_monotonic_timer monotonic_timer;//单调定时器

    /** Difference between internal time (maybe from clock_gettime) and
     * gettimeofday. */
    struct timeval tv_clock_diff;//内部时间(可能来自clock_gettime)和gettimeofday之间的差异。
    /** Second in which we last updated tv_clock_diff, in monotonic time. */
    time_t last_updated_clock_diff;//在第二次更新中,我们在单调时间内最后更新了tv_clock_diff。

#ifndef EVENT__DISABLE_THREAD_SUPPORT
    /* threading support */

    /* 线程支持 */
    /** The thread currently running the event_loop for this base */
    unsigned long th_owner_id;//当前运行此基的event_ loop的线程
    /** A lock to prevent conflicting accesses to this event_base */
    void *th_base_lock;//用于防止对此event_ base的冲突访问的锁
    /** A condition that gets signalled when we're done processing an
     * event with waiters on it. */
    void *current_event_cond;//当我们处理完一个有服务员的事件时,发出信号的条件。
    /** Number of threads blocking on current_event_cond. */
    int current_event_waiters;//在current_event_cond上阻塞的线程数。
#endif
    /** The event whose callback is executing right now */
    struct event_callback *current_event;//当前正在执行其回调的事件

#ifdef _WIN32
    /** IOCP support structure, if IOCP is enabled. */
    struct event_iocp_port *iocp;//IOCP支持结构,如果启用了IOCP(异步io操作的接口)
#endif

    /** Flags that this base was configured with */
    enum event_base_config_flag flags;//基础配置时使用的标志

    struct timeval max_dispatch_time;//最大调度时间
    int max_dispatch_callbacks;//最大调度回调
    int limit_callbacks_after_prio;//限制prio后的回调

    /* Notify main thread to wake up break, etc. */

   /*通知主线程唤醒、中断等。 */
    /** True if the base already has a pending notify, and we don't need
     * to add any more. */
    int is_notify_pending;//如果基础已经有一个挂起的notify,并且我们不需要再添加任何通知,则为True。
    /** A socketpair used by some th_notify functions to wake up the main
     * thread. */
    evutil_socket_t th_notify_fd[2];//一些th_ notify函数用来唤醒主线程的socketpair。
    /** An event used by some th_notify functions to wake up the main
     * thread. */
    struct event th_notify;//一些th_ notify函数用来唤醒主线程的事件。
    /** A function used to wake up the main thread from another thread. */
    int (*th_notify_fn)(struct event_base *base);//用于从另一个线程唤醒主线程的函数。

    /** Saved seed for weak random number generator. Some backends use
     * this to produce fairness among sockets. Protected by th_base_lock. */
    struct evutil_weakrand_state weakrand_seed;//为弱随机数生成器保存种子。一些后端使用它在套接字之间产生公平性。由th_ base_。

    /** List of event_onces that have not yet fired. */
    LIST_HEAD(once_event_list, event_once) once_events;//尚未激发的事件列表

};

这样应该对event_base有一个模糊的了解了       >_<

你可能感兴趣的:(libevent,开发语言,c++,c语言,网络)