libevent源码分析(3)--2.1.8--结构体struct event_base和struct eventop

10 篇文章 6 订阅
3 篇文章 0 订阅

一、struct eventop结构体

struct eventop {
    /** The name of this backend. */
     // 后台方法名字,即epoll,select,poll等
    const char *name;

    /** Function to set up an event_base to use this backend.  It should
     * create a new structure holding whatever information is needed to
     * run the backend, and return it.  The returned pointer will get
     * stored by event_init into the event_base.evbase field.  On failure,
     * this function should return NULL. */
     // 配置libevent句柄event_base使用当前后台方法;他应该创建新的数据结构,
     // 隐藏了后台方法运行所需的信息,然后返回这些信息的结构体,为了支持多种
     // 结构体,因此返回void*;返回的指针将保存在event_base.evbase中;如果失败,
     // 将返回NULL
    void *(*init)(struct event_base *);

    /** Enable reading/writing on a given fd or signal.  'events' will be
     * the events that we're trying to enable: one or more of EV_READ,
     * EV_WRITE, EV_SIGNAL, and EV_ET.  'old' will be those events that
     * were enabled on this fd previously.  'fdinfo' will be a structure
     * associated with the fd by the evmap; its size is defined by the
     * fdinfo field below.  It will be set to 0 the first time the fd is
     * added.  The function should return 0 on success and -1 on error.
     */
     // 使给定的文件描述符或者信号变得可读或者可写。’events’将是我们尝试添加的
     // 事件类型:一个或者更多的EV_READ,EV_WRITE,EV_SIGNAL,EV_ET。’old’是这些事件
     // 先前的事件类型;’fdinfo’将是fd在evmap中的辅助结构体信息,它的大小由下面的
     // fdinfo_len给出。fd第一次添加时将设置为0.成功则返回0,失败则返回-1
    int (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);

    /** As "add", except 'events' contains the events we mean to disable. */
     // 删除事件
    int (*del)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);

    /** Function to implement the core of an event loop.  It must see which
        added events are ready, and cause event_active to be called for each
        active event (usually via event_io_active or such).  It should
        return 0 on success and -1 on error.
     */
     // event_loop实现的核心代码。他必须察觉哪些添加的事件已经准备好,然后触发每个
     // 活跃事件都被调用(通常是通过event_io_active或者类似这样)。成功返回0,失败则-1
    int (*dispatch)(struct event_base *, struct timeval *);

    /** Function to clean up and free our data from the event_base. */
     // 清除event_base并释放数据
    void (*dealloc)(struct event_base *);

    /** Flag: set if we need to reinitialize the event base after we fork.
     */
     // 在执行fork之后是否需要重新初始化的标识位
    int need_reinit;

    /** Bit-array of supported event_method_features that this backend can
     * provide. */
     // 后台方法可以提供的特征
     // enum event_method_feature {
     // 边沿触发
     // EV_FEATURE_ET = 0x01,
     // 要求事后台方法在调度很多事件时大约为O(1)操作,select和poll无法提供这种特征,
     // 这两种方法具有N个事件时,可以提供O(N)操作
    // EV_FEATURE_O1 = 0x02,

     // 后台方法可以处理各种文件描述符,而不仅仅是sockets
    // EV_FEATURE_FDS = 0x04,
    /** Require an event method that allows you to use EV_CLOSED to detect
     * connection close without the necessity of reading all the pending data.
     *
     * Methods that do support EV_CLOSED may not be able to provide support on
     * all kernel versions.
     **/
     // 要求后台方法允许使用EV_CLOSED特征检测链接是否中断,而不需要读取
     // 所有未决数据;但是不是所有内核都能提供这种特征
    // EV_FEATURE_EARLY_CLOSE = 0x08
    // };
    enum event_method_feature features;

    /** Length of the extra information we should record for each fd that
        has one or more active events.  This information is recorded
        as part of the evmap entry for each fd, and passed as an argument
        to the add and del functions above.
     */
     // 应该为每个文件描述符保留的额外信息长度,额外信息可能包括一个或者多个
     // 活跃事件。这个信息是存储在每个文件描述符的evmap中,然后通过参数传递
     // 到上面的add和del函数中。
    size_t fdinfo_len;
};



二、static const struct eventop *eventops[] 

/* Array of backends in order of preference. */
后台方法的全局静态数组
static const struct eventop *eventops[] = {
#ifdef EVENT__HAVE_EVENT_PORTS
    &evportops,
#endif
#ifdef EVENT__HAVE_WORKING_KQUEUE
    &kqops,
#endif
#ifdef EVENT__HAVE_EPOLL
    &epollops,
#endif
#ifdef EVENT__HAVE_DEVPOLL
    &devpollops,
#endif
#ifdef EVENT__HAVE_POLL
    &pollops,
#endif
#ifdef EVENT__HAVE_SELECT
    &selectops,
#endif
#ifdef _WIN32
    &win32ops,
#endif
    NULL
};




三、struct event_base结构体

struct event_base {
    /** Function pointers and other data to describe this event_base's
     * backend. */
     // 实际使用后台方法的句柄,实际上指向的是静态全局数组变量
     // ,从静态全局变量eventops中选择
    const struct eventop *evsel;
    /** Pointer to backend-specific data. */
     // 指向后台特定的数据,是由evsel->init返回的句柄
     // 实际上是对实际后台方法所需数据的封装,void出于兼容性考虑
    void *evbase;

    /** List of changes to tell backend about at next dispatch.  Only used
     * by the O(1) backends. */
     // 告诉后台方法下一次调度的变化列表
    struct event_changelist changelist;

    /** Function pointers used to describe the backend that this event_base
     * uses for signals */
     // 用于描述当前event_base用于信号的后台方法
    const struct eventop *evsigsel;
    /** Data to implement the common signal handler code. */
     // 用于实现公用信号句柄的代码
    struct evsig_info sig;

    /** 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 */
     // 添加到event_base上事件总数
    int event_count;
    /** Maximum number of total events added to this event_base */
     // 添加到event_base上的最大个数
    int event_count_max;
    /** Number of total events active in this event_base */
     // 当前event_base中活跃事件的个数
    int event_count_active;
    /** Maximum number of total events active in this event_base */
     // 当前event_base中活跃事件的最大个数
    int event_count_active_max;

    /** Set if we should terminate the loop once we're done processing
     * events. */
     // 一旦我们完成处理事件了,如果我们应该终止loop,可以设置这个
    int event_gotterm;
    /** Set if we should terminate the loop immediately */
     // 如果需要中止loop,可以设置这个变量
    int event_break;
    /** Set if we should start a new instance of the loop immediately. */
     // 如果启动新实例的loop,可以设置这个
    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. */
     // 防止event_base_loop重入的
    int running_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 */
     // 设置已经在loop中设置为’active’的deferred_cbs的个数,这是为了避免
     // 饥饿的hack方法;只需要使用event_config_set_max_dispatch_interval’s的
     // max_callbacks特征就可以变的更智能
    int n_deferreds_queued;

    /* 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.
     */
     // 存储激活事件的event_callbacks的队列,这些event_callbacks都需要调用;
     // 数字越小优先级越高
    struct evcallback_list *activequeues;
    /** The length of the activequeues array */
     // 活跃队列的长度
    int nactivequeues;
    /** 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;

    /* 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;
    /** The number of entries used in common_timeout_queues */
     // 公用超时队列中的项目个数
    int n_common_timeouts;
    /** The total size of common_timeout_queues. */
    // 公用超时队列的总个数
    int n_common_timeouts_allocated;

    /** 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. */
     // 存储时间:用来避免频繁调用gettimeofday/clock_gettime
    struct timeval tv_cache;

     // monotonic格式的时间
    struct evutil_monotonic_timer monotonic_timer;

    /** Difference between internal time (maybe from clock_gettime) and
     * gettimeofday. */
     // 内部时间(可以从clock_gettime获取)和gettimeofday之间的差异
    struct timeval tv_clock_diff;
    /** Second in which we last updated tv_clock_diff, in monotonic time. */
     // 更新内部时间的间隔秒数
    time_t last_updated_clock_diff;

#ifndef EVENT__DISABLE_THREAD_SUPPORT
    /* threading support */
    /** The thread currently running the event_loop for this base */
    unsigned long th_owner_id;
    /** A lock to prevent conflicting accesses to this event_base */
    void *th_base_lock;
    /** 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;
#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;
#endif

    /** Flags that this base was configured with */
     // event_base配置的特征值
     // 多线程调用是不安全的,单线程非阻塞模式
    // EVENT_BASE_FLAG_NOLOCK = 0x01,
     // 忽略检查EVENT_*等环境变量
    // EVENT_BASE_FLAG_IGNORE_ENV = 0x02,
     // 只用于windows
    // EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,
     // 不使用缓存的时间,每次回调都会获取系统时间
    // EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,
     // 如果使用epoll方法,则使用epoll内部的changelist
    // EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST = 0x10,
     // 使用更精确的时间,但是可能性能会降低
    // EVENT_BASE_FLAG_PRECISE_TIMER = 0x20
    enum event_base_config_flag flags;

     // 最大调度时间间隔
    struct timeval max_dispatch_time;
     // 最大调度的回调函数个数
    int max_dispatch_callbacks;
     // 优先级设置之后,对于活跃队列中子队列个数的限制
     // 但是当子队列个数超过这个限制之后,会以实际的回调函数个数为准
    int limit_callbacks_after_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. */
     // 如果event_base已经有关于未决事件的通知,那么我们就不需要再次添加了
    int is_notify_pending;
    /** A socketpair used by some th_notify functions to wake up the main
     * thread. */
     // 某些th_notify函数用于唤醒主线程的socket pair,0读1写
    evutil_socket_t th_notify_fd[2];
    /** An event used by some th_notify functions to wake up the main
     * thread. */
     // 用于th_notify函数唤醒主线程的事件
    struct event 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. */
     // 保存弱随机数产生器的种子。某些后台方法会使用这个种子来公平的选择
     // sockets。
    struct evutil_weakrand_state weakrand_seed;

    /** List of event_onces that have not yet fired. */
    LIST_HEAD(once_event_list, event_once) once_events;

};


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值