目录

event

event_base

eventop

evcb_closure

event_callback

event_changelist

evsig_info

event_io_map

event_iocp_port


event

struct event {// 事件回调  下文有注解struct event_callback ev_evcallback; //超时管理union {TAILQ_ENTRY(event) ev_next_with_common_timeout;   // 事件队列int min_heap_idx;                 // 事件在最小堆中的index} ev_timeout_pos;evutil_socket_t ev_fd;                // socket 描述符// 下文有注解 struct event_base *ev_base;union {// 使用独写事件struct {LIST_ENTRY (event) ev_io_next; // 事件链表 ,链接下一个事件struct timeval ev_timeout;     // 事件超时时间} ev_io;// 使用信号事件struct {LIST_ENTRY (event) ev_signal_next; // 事件链表 ,链接下一个事件short ev_ncalls;                   // 回调数量short *ev_pncalls;                 // 允许在回调中删除  } ev_signal;} ev_;// ev_events : // EV_TIMEOUT    0x01  超时// EV_READ      0x02  读// EV_WRITE      0x04  写// EV_SIGNAL 0x08  信号// EV_PERSIST   0x10  持久事件 激活时不会自动删除,超时激活 超时重置为0// EV_ET     0x20  边缘触发// EV_FINALIZE  0x40  终止事件 event_del不会阻塞 ,需要使用 event_finalize 或// event_free_finalize 来保证线程安全// EV_CLOSED  0x80  连接关闭short ev_events;   short ev_res;  // 结果传递给事件回调struct timeval ev_timeout;                 // 事件超时时间
};

event_base

struct event_base {// 函数指针和其他数据来描述event_base的后端,也就是所谓的epoll iocp kqueue等// 下文有注解样例const struct eventop *evsel;// 指向后端特定数据指针,上面 evsel Init初始化后返回值赋值给 evbasevoid *evbase;// 事件变化列表 ,有变化的事件会进行下一次分发 下文有注解struct event_changelist changelist;// 用函数指针来描述event_base的后端,用于信号const struct eventop *evsigsel;// 处理通用信号数据 下文有注解struct evsig_info sig;// 虚拟事件数量int virtual_event_count;// 最大活跃虚拟事件数量int virtual_event_count_max;// 添加到此event_base的事件的数量int event_count;// 添加到此event_base的事件的最大数量int event_count_max;// 事件活跃数量int event_count_active;// 事件最大活跃数量int event_count_active_max;// 设置是否在完成事件处理后终止循环int event_gotterm;// 设置是否应该立即终止循环int event_break;// 设置是否立即开始一个新的循环实例int event_continue;// 当前正在运行事件的优先级int event_running_priority;// 设置我们是否正在运行 event_base_loop 函数,以防止可重入调用int running_loop;// 设置在循环,防饥饿标志int n_deferreds_queued;//此处用双向队列管理激活的事件// TAILQ_HEAD(evcallback_list, event_callback);//  #define TAILQ_HEAD(name, type)                       \// struct name {                               \//     struct type *tqh_first; /* first element */         \//     struct type **tqh_last; /* addr of last next element */     \// }struct evcallback_list *activequeues;// activequeues 链表长度int nactivequeues;// 下次激活时候处理 的 evcallback_list  struct evcallback_list active_later_queue;// 公共超时链表struct common_timeout_list **common_timeout_queues;// common_timeout_queues 队列中的数量int n_common_timeouts;// common_timeout_queues 的sizeint n_common_timeouts_allocated;// 事件读写Map看下文有注解 struct event_io_map io;// 信号到事件的映射struct event_signal_map sigmap;// 超时事件的优先队列struct min_heap timeheap;// 存储时间值,用于避免调用 gettimeofday/clock_gettimestruct timeval tv_cache;// 系统启动以后流逝的时间struct evutil_monotonic_timer monotonic_timer;/** Difference between internal time (maybe from clock_gettime) and* gettimeofday. */struct timeval tv_clock_diff; // 时钟差异// 上次更新tv_clock_diff的第二个时间time_t last_updated_clock_diff;#ifndef EVENT__DISABLE_THREAD_SUPPORT  // 多线程管理// 当前loop的线程IDunsigned long th_owner_id;// event_base 的锁,针对多线程,处理同步void *th_base_lock;// 条件变量,处理同步void *current_event_cond;阻塞在 current_event_cond 上的线程数量int current_event_waiters;
#endif// 正在执行回调的事件 下文有详细注解struct event_callback *current_event;#ifdef _WIN32// IOCP 支持结构 下文有详细注解struct event_iocp_port *iocp;
#endif// 配置标志/*enum event_base_config_flag {// 不给这个event_base分配锁,即使有锁设定,可以省去加锁解锁消耗,但多线程下不安全EVENT_BASE_FLAG_NOLOCK = 0x01,// 不检查 EVENT_* 环境变量EVENT_BASE_FLAG_IGNORE_ENV = 0x02,// 仅对windows有效,启用Libevent时 bufferevent_socket_new() 和evconn_listener_new() 将使用 IOCP 支持的实现,而不是在需要时才使用EVENT_BASE_FLAG_STARTUP_IOCP = 0x04,// 在每个超时回调后检测当前时间,而不是在超时回调前检测EVENT_BASE_FLAG_NO_CACHE_TIME = 0x08,// 如果使用EPOLL后端,使用change-list 是安全的,可以让代码运行更快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;   // 回调函数优先级限制int is_notify_pending;   //通知主线程唤醒休息的线程// 一个socketpair, 使用 th_notify_fn 函数唤醒主线程evutil_socket_t th_notify_fd[2];// 事件触发的时候 使用 th_notify_fn 函数唤醒主线程struct event th_notify;// 子线程唤醒主线程的回调函数int (*th_notify_fn)(struct event_base *base);// 随机数种子 受 th_base_lock 保护struct evutil_weakrand_state weakrand_seed;// 尚未触发的通过event_once注册的事件链表LIST_HEAD(once_event_list, event_once) once_events;};

eventop

struct eventop {/** 后端的名字. */const char *name;//初始化一个event_base 来使用这个后端函数,运行得到返回值会赋给event_base.evbasevoid *(*init)(struct event_base *);// 激活一个给定的文件描述符或者信号上启动读/写,例 EV_READ,EV_WRITE,EV_SIGNAL, EV_ETint (*add)(struct event_base *, evutil_socket_t fd, short old, short events, void *fdinfo);// del和add相反int (*del)(struct event_base *, evutil_socket_t fd,short old, short events, void *fdinfo);// 事件循环核心函数 事件就绪时为每个事件调用event_activeint (*dispatch)(struct event_base *, struct timeval *);// 清除和释放 event_basevoid (*dealloc)(struct event_base *);// 在fork后是否需要重新初始化event_base int need_reinit;// 用于描述 event_base 提供了哪些功能的标志
event_config_require_features() 告诉 Libevent 仅在您的event_base 实现了一个给定的特性// event_base_get_features() 以查看哪些功能可用// event_config_require_features()输入应用程序要求的必需 event 方法功能// EV_FEATURE_ET = 0x01, 边缘触发// EV_FEATURE_O1 = 0x02, O(1)事件触发 不轮询 epoll,kqueue// EV_FEATURE_FDS = 0x04, 可以处理包括sockets在内的各种文件描述符// EV_FEATURE_EARLY_CLOSE = 0x08, 可以使用EV_CLOSED检测连接关闭,不需读完所有挂起数据enum event_method_feature features;// 文件描述符记录的信息长度,会作为参数传给上面的add和delsize_t fdinfo_len;
};/* 例const struct eventop epollops = {"epoll",epoll_init,epoll_nochangelist_add,epoll_nochangelist_del,epoll_dispatch,epoll_dealloc,1, // need reinit EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_EARLY_CLOSE,0};*/

evcb_closure

// 一个常规事件 使用 evcb_callback 回调
#define EV_CLOSURE_EVENT 0
// 一个信号事件 使用 evcb_callback 回调
#define EV_CLOSURE_EVENT_SIGNAL 1
// 一个持久的非信号事件 使用 evcb_callback 回调
#define EV_CLOSURE_EVENT_PERSIST 2
// 一个简单的回调 使用 evcb_selfcb 回调
#define EV_CLOSURE_CB_SELF 3
// 最终回调 使用 evcb_cbfinalize 回调
#define EV_CLOSURE_CB_FINALIZE 4
// 一个终止事件 使用 evcb_evfinalize 回调
#define EV_CLOSURE_EVENT_FINALIZE 5
// 结束后应该被释放的事件 使用 evcb_evfinalize 回调
#define EV_CLOSURE_EVENT_FINALIZE_FREE 6

event_callback

struct event_callback {TAILQ_ENTRY(event_callback) evcb_active_next; // 下一个event_callback实例的指针/* evcb_flags #define EVLIST_TIMEOUT       0x01  // 超时,事件在time min_heap堆中#define EVLIST_INSERTED        0x02  // 事件在已注册事件链表中#define EVLIST_SIGNAL       0x04  // 信号,目前暂未使用#define EVLIST_ACTIVE      0x08  // 事件在激活链表中#define EVLIST_INTERNAL        0x10  // 内部使用标记#define EVLIST_ACTIVE_LATER 0x20  // 延迟激活,事件在下一次激活链表中#define EVLIST_FINALIZING   0x40  // 事件已终止#define EVLIST_INIT        0x80      // 事件初始化完成#define EVLIST_ALL          0xff  // 判断合法性*/short evcb_flags; // 选择回调类型ev_uint8_t evcb_pri; /* 较小的数字具有更高的优先级 */ev_uint8_t evcb_closure;/* 允许采用不同类型的事件回调 */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;
};

event_changelist

struct event_changelist{struct event_change *changes;int n_changes; int changes_size;};struct event_change {// 改变事件的文件描述符或信号evutil_socket_t fd;// 更改前的旧事件short old_events;// 更改标志 unsigned charev_uint8_t read_change;ev_uint8_t write_change;ev_uint8_t close_change;};

evsig_info

struct evsig_info {/* Event watching ev_signal_pair[1] */struct event ev_signal;/* Socketpair 从信号处理handler出发送通知*/evutil_socket_t ev_signal_pair[2];// 如果添加了 ev_signal 事件则为真int ev_signal_added;// 信号计数int ev_n_signals_added;
#ifdef EVENT__HAVE_SIGACTIONstruct sigaction **sh_old;  // 指针数组,存放信号处理函数
#elseev_sighandler_t **sh_old;  // 指针数组,存放信号处理函数
#endif// 数组指针sizeint sh_old_max;
};

event_io_map

#ifdef _WIN32    // 如果在win32中
#define EVMAP_USE_HT  // 则定义 EVMAP_USE_HT
#endif/* #define HT_CACHE_HASH_VALS */
#ifdef EVMAP_USE_HT
#define HT_NO_CACHE_HASH_VALUES
#include "ht-internal.h"
struct event_map_entry;
HT_HEAD(event_io_map, event_map_entry);  // 如果在windows环节下,event_io_map会使用哈希结构
#else
#define event_io_map event_signal_map    // 否则当成 event_signal_map 来使用
#endifstruct event_signal_map
{void **entries; // 二级指针,evmap_signal* 数组int nentries;   // evmap_signal* 个数
};#ifdef HT_NO_CACHE_HASH_VALUES
#define HT_ENTRY(type)                          \struct {                                      \struct type *hte_next;                      \}
#else
#define HT_ENTRY(type)                          \struct {                                      \struct type *hte_next;                      \unsigned hte_hash;                          \}
#endif#define HT_HEAD(name, type)                                             \struct name {                                                         \/* 哈希表,可当做数组. */                                        \struct type **hth_table;                                            \/* 哈希表 数组长度 */                                   \unsigned hth_table_length;                                          \/* 元素个数 */                     \unsigned hth_n_entries;                                             \/* 最大扩容限制 */ \unsigned hth_load_limit;                                            \/* 索引 */             \int hth_prime_idx;                                                  \}#ifdef EVMAP_USE_HT
struct event_map_entry {/* struct {                                   struct type *hte_next;  // 构成链表#ifndef HT_NO_CACHE_HASH_VALUES             unsigned hte_hash;  // windows 下没有#endif    }map_node;HT_ENTRY(event_map_entry) map_node;evutil_socket_t fd; // 文件描述符union { /*#define LIST_HEAD(name, type)                       \struct name {                              \struct type *lh_first;  /* first element */            \}#endif /* !LIST_HEAD */struct evmap_io{// LIST_HEAD (event_dlist, event); 声明在上面struct event_dlist events;ev_uint16_t nread;ev_uint16_t nwrite;ev_uint16_t nclose;};struct evmap_io evmap_io; // 记录读写fd及数量} ent;
};

event_iocp_port

struct event_iocp_port {// 端口HANDLE port;// 临界区 锁CRITICAL_SECTION lock;// 线程数量short n_threads;// 关闭标志short shutdown;// 多久检查一次关闭和其他条件long ms;// 等待事件的线程HANDLE *threads;// 在当前端口上打开线程的数量short n_live_threads;// 完成关闭时发出的信号的信号量HANDLE *shutdownSemaphore;
};

个人理解,不一定都是对的,仅供参考

Libevent 源码学习笔记(1)event 与 event_base相关推荐

  1. Libevent源码学习笔记一:event2/event.h

    一.libevent标准使用方法: 每个程序使用Libevent必须include <event2/event.h> 头文件,并 传给 -levent  链接器.如果只是想使用主要的eve ...

  2. Apache log4j-1.2.17源码学习笔记

    (1)Apache log4j-1.2.17源码学习笔记 http://blog.csdn.net/zilong_zilong/article/details/78715500 (2)Apache l ...

  3. Java多线程之JUC包:Semaphore源码学习笔记

    若有不正之处请多多谅解,并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/go2sea/p/5625536.html Semaphore是JUC ...

  4. RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的?

    RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 文章目录 RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 前言 项目 ...

  5. Vuex 4源码学习笔记 - 通过Vuex源码学习E2E测试(十一)

    在上一篇笔记中:Vuex 4源码学习笔记 - 做好changelog更新日志很重要(十) 我们学到了通过conventional-changelog来生成项目的Changelog更新日志,通过更新日志 ...

  6. Vuex 4源码学习笔记 - Vuex是怎么与Vue结合?(三)

    在上一篇笔记中:Vuex源码学习笔记 - Vuex开发运行流程(二) 我们通过运行npm run dev命令来启动webpack,来开发Vuex,并在Vuex的createStore函数中添加了第一个 ...

  7. jquery源码学习笔记三:jQuery工厂剖析

    jquery源码学习笔记二:jQuery工厂 jquery源码学习笔记一:总体结构 上两篇说过,query的核心是一个jQuery工厂.其代码如下 function( window, noGlobal ...

  8. 雷神FFMpeg源码学习笔记

    雷神FFMpeg源码学习笔记 文章目录 雷神FFMpeg源码学习笔记 读取编码并依据编码初始化内容结构 每一帧的视频解码处理 读取编码并依据编码初始化内容结构 在开始编解码视频的时候首先第一步需要注册 ...

  9. PHP Yac cache 源码学习笔记

    YAC 源码学习笔记 本文地址 http://blog.csdn.net/fanhengguang_php/article/details/54863955 config.m4 检测系统共享内存支持情 ...

最新文章

  1. 创建react应用程序_通过创建食谱应用程序来学习在React中使用API
  2. 城市大脑不仅是AI系统,更是结合人类智慧的混合智能巨系统
  3. 牛津大学入学面试就这?组队选个颜色?背后的逻辑水深得很
  4. python各个解释器的用途-Python解释器有哪些?Python解释器种类
  5. python 测试用例中设置执行时间_Python基于unittest实现测试用例执行
  6. hdu 6386 Age of Moyu (重边判断)
  7. SAP Spartacus B2B页面内容的动态注入
  8. eclipse中对于Java虚拟机参数的设置与思考
  9. Android 代码混淆(一)
  10. 读书笔记-泛型有限通配符
  11. MSCRM与MS人立方关系的集成
  12. 视频播放的时候不拦截OK键
  13. NVivo 12 Mac的大规模部署
  14. 颜色科学与计算机测色配色实用技术,颜色科学与计算机测色配色实用技术
  15. #PLC_梯形图简史(内含早期梯形图编程珍贵画面)
  16. [996]如何申请高德地图用户Key
  17. Simulink仿真设置和Scope示波器的使用[方案]
  18. git subtree pull 错误 Working tree has modifications
  19. Java 全角半角转换工具类
  20. 解决 Edge 浏览器 阻止下载

热门文章

  1. 普通设备能不能接入TSN时间敏感网络?
  2. 分享微信抽奖小程序制作步骤_微信抽奖小程序怎么开发
  3. 矩阵股份上市首日跌破发行价:振幅达10%,王冠为实际控制人
  4. 插入数据时异常 Unknown column ‘XXX‘ in ‘field list‘
  5. 微视狂砸千万补贴,却惨遭微信封杀,亲兄弟明算账
  6. 使用PIL为图片添加水印[python]
  7. 最全流媒体协议详细总结介绍(RTP/RTCP/RTSP/RTMP/MMS/HLS/HTTP/ HTTP-FLV(HDL) /SDP)
  8. 两波形相位差的计算值_光纤耦合器怎么计算
  9. 数据的统计量特征---懒得整理
  10. VisionPro文档 -- 在单个作业里的多相机采集