3.7.5 event_loop:事件循环
来源:互联网 发布:淘宝的消费总额怎么看 编辑:程序博客网 时间:2024/06/07 21:10
当完成了文件描述符与回调函数的“绑定”后,可执行事件循环:循环选择触发事件的文件描述符,执行其回调函数。在event_loop中也执行了定时事件。
/util/event.c998 void event_loop(int delay)999 {1000 const char *myname = "event_loop";1001 static int nested;10021003 #if(EVENTS_STYLE == EVENTS_STYLE_SELECT)1004 fd_set rmask;1005 fd_set wmask;1006 fd_set xmask;1007 struct timeval tv;1008 struct timeval *tvp;1009 int new_max_fd;10101011 #else1012 EVENT_BUFFER event_buf[100];1013 EVENT_BUFFER *bp;10141015 #endif
1003-1015 为select多路复用函数准备各个参数。
1016 int event_count;1017 EVENT_TIMER *timer;1018 int fd;1019 EVENT_FDTABLE *fdp;1020 int select_delay;10211022 if (EVENT_INIT_NEEDED())1023 event_init();
1022-1023 如果event_init没有运行,先运行event_init。
10241025 /*1026 * XXX Also print the select() masks?1027 */1028 if (msg_verbose > 2) {1029 RING *ring;10301031 FOREACH_QUEUE_ENTRY(ring,&event_timer_head) {1032 timer = RING_TO_TIMER(ring);1033 msg_info("%s: time left %3dfor 0x%lx 0x%lx", myname,1034 (int) (timer->when -event_present),1035 (long) timer->callback,(long) timer->context);1036 }1037 }10381039 /*1040 * Find out when the next timer would gooff. Timer requests are sorted.1041 * If any timer is scheduled, adjust thedelay appropriately.1042 */1043 if ((timer =FIRST_TIMER(&event_timer_head)) != 0) {1044 event_present = time((time_t *) 0);1045 if ((select_delay = timer->when -event_present) < 0) {1046 select_delay = 0;1047 } else if (delay >= 0 &&select_delay > delay) {1048 select_delay = delay;1049 }1050 } else {1051 select_delay = delay;1052 }
1043-1052 确定多路复用函数的等待时间
多路复用函数有等待时间参数。event_loop的参数delay就是用来确定这个值的——但不是唯一由它确定。由于多路复用函数会引发阻塞,所以确定等待时间的原则是:如果当前定时事件已经超时,来不及执行,则将select的等待时间置0,即检查后立即返回,以免妨碍下一个时间事件的执行。否则,如果当前时间事件还来得及执行,那多路复用函数可以阻塞到这个时间事件执行前——这样一方面多路复用函数可以有机会捕获事件,同时也不会影响定时事件的执行。
1053 if (msg_verbose > 2)1054 msg_info("event_loop:select_delay %d", select_delay);10551056 /*1057 * Negative delay means: wait untilsomething happens. Zero delay means:1058 * poll. Positive delay means: wait atmost this long.1059 */1060 #if(EVENTS_STYLE == EVENTS_STYLE_SELECT)1061 if (select_delay < 0) {1062 tvp = 0;1063 } else {1064 tvp = &tv;1065 tv.tv_usec = 0;1066 tv.tv_sec = select_delay;1067 }10681069 /*1070 * Pause until the next event happens.When select() has a problem, don't1071 * go into a tight loop. Allow select() tobe interrupted due to the1072 * arrival of a signal.1073 */1074 rmask = event_rmask;1075 wmask = event_wmask;1076 xmask = event_xmask;10771078 event_count = select(event_max_fd + 1,&rmask, &wmask, &xmask, tvp);1079 if (event_count < 0) {1080 if (errno != EINTR)1081 msg_fatal("event_loop:select: %m");1082 return;1083 }1084 #else
//执行其他I/O多路复用函数
1093 #endif
1060-1093 执行多路复用函数。
10941095 /*1096 * Before entering the applicationcall-back routines, make sure we1097 * aren't being called from a call-backroutine. Doing so would make us1098 * vulnerable to all kinds of raceconditions.1099 */1100 if (nested++ > 0)1101 msg_panic("event_loop: recursivecall");11021103 /*1104 * Deliver timer events. Allow theapplication to add/delete timer queue1105 * requests while it is being called back.Requests are sorted: we keep1106 * running over the timer request queuefrom the start, and stop when we1107 * reach the future or the list end. Wealso stop when we reach a timer1108 * request that was added by a call-backthat was invoked from this1109 * event_loop() call instance, for reasonsthat are explained below.1110 *1111 * To avoid dangling pointer problems 1)we must remove a request from the1112 * timer queue before delivering its eventto the application and 2) we1113 * must look up the next timer request*after* calling the application.1114 * The latter complicates the handling ofzero-delay timer requests that1115 * are added by event_loop() call-backfunctions.1116 *1117 * XXX When a timer event call-backfunction adds a new timer request,1118 * event_request_timer() labels therequest with the event_loop() call1119 * instance that invoked the timer eventcall-back. We use this instance1120 * label here to prevent zero-delay timerrequests from running in a1121 * tight loop and starving I/O events. Tomake this solution work,1122 * event_request_timer() appends a newrequest after existing requests1123 * for the same time slot.1124 */1125 event_present = time((time_t *) 0);1126 event_loop_instance += 1;11271128 while ((timer =FIRST_TIMER(&event_timer_head)) != 0) {1129 if (timer->when > event_present)1130 break;1131 if (timer->loop_instance ==event_loop_instance)1132 break;1133 ring_detach(&timer->ring); /* first this */1134 if (msg_verbose > 2)1135 msg_info("%s: timer 0x%lx0x%lx", myname,1136 (long)timer->callback, (long) timer->context);1137 timer->callback(EVENT_TIME,timer->context); /* then this */1138 myfree((void *) timer);1139 }
1128-1139 执行时间事件。取得当前未执行的时间事件(EVENT_TIMER节点),如果该时间事件已过期,则跳出。如果该时间事件不是当前上下文的时间事件,则跳出。否则取下当前EVENT_TIMER节点,执行其回调函数。由于event_loop函数总会在循环中被调用。所以在每一轮循环中会选择一个当前可执行时间事件执行。
11401141 /*1142 * Deliver I/O events. Allow the application to cancel event requests1143 * while it is being called back. To this end, we keep an eye on the1144 * contents of event_xmask, so that we deliver only events that are still1145 * wanted. We do not change the event request masks. It is up to the1146 * application to determine when a read or write is complete.1147 */1148 #if (EVENTS_STYLE ==EVENTS_STYLE_SELECT)1149 if (event_count > 0) {1150 for (new_max_fd = 0, fd = 0; fd <= event_max_fd; fd++) {1151 if (FD_ISSET(fd,&event_xmask)) {1152 new_max_fd = fd;1153 /* In case event_fdtable isupdated. */1154 fdp = event_fdtable + fd;1155 if (FD_ISSET(fd, &xmask)){1156 if (msg_verbose > 2)1157 msg_info("%s:exception fd=%d act=0x%lx 0x%lx", myname,1158 fd, (long)fdp->callback, (long) fdp->context);1159 fdp->callback(EVENT_XCPT, fdp->context);1160 } else if (FD_ISSET(fd,&wmask)) {1161 if (msg_verbose > 2)1162 msg_info("%s:write fd=%d act=0x%lx 0x%lx", myname,1163 fd, (long)fdp->callback, (long) fdp->context);1164 fdp->callback(EVENT_WRITE, fdp->context);1165 } else if (FD_ISSET(fd,&rmask)) {1166 if (msg_verbose > 2)1167 msg_info("%s:read fd=%d act=0x%lx 0x%lx", myname,1168 fd, (long)fdp->callback, (long) fdp->context);1169 fdp->callback(EVENT_READ, fdp->context);1170 }1171 }1172 }1173 event_max_fd = new_max_fd;1174 }1175 #else//执行其他I/O多路复用函数的回调函数。1201 #endif1202 nested--;1203 }
1148-1203 扫描多路复用函数文件描述符组,执行读、写、异常事件。
0 0
- 3.7.5 event_loop:事件循环
- 事件循环
- 循环事件事件监听
- js--事件--事件循环
- js--事件--事件循环
- 文章5:Nginx源码分析--事件循环
- 文章5:Nginx源码分析--事件循环
- Node.js学习5- 事件循环
- libevent笔记-事件/事件循环
- Qt:事件和事件循环
- Qt事件和事件循环
- JS 循环设置事件
- QT事件循环
- QT事件循环
- Nginx的事件循环
- 四、事件循环
- 线程和事件循环
- JavaScript事件循环
- hdu1087 LIS变形
- 快速熟悉项目代码
- 对于MathType中公式与文字错位的问题怎么解决
- Spring源代码解析(三):Spring JDBC
- C#更改groupbox边框颜色
- 3.7.5 event_loop:事件循环
- 64位win7系统中JDK的安装及环境变量的配置
- Android Studio常用插件
- Linux下undefined reference to ‘pthread_create’问题解决
- 浏览器、操作系统DNS缓存时间
- hdu1029 技巧
- ListView使用ViewHolder模式提高效率
- SQL实现Split功能
- 使用CHOOSE使用举例-动态排序字段