static void event_loop(ACL_EVENT *eventp) { const char *myname = "event_loop"; EVENT_KERNEL *ev = (EVENT_KERNEL *) eventp; ACL_EVENT_NOTIFY_TIME timer_fn; void *timer_arg; ACL_EVENT_TIMER *timer; int delay, nready; ACL_EVENT_FDTABLE *fdp; EVENT_BUFFER *bp; delay = (int) (eventp->delay_sec * 1000 + eventp->delay_usec / 1000); if (delay < 0) delay = 0; /* 0 milliseconds at least */ /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); /* 根据定时器任务的最近任务计算 epoll/kqueue/devpoll 的检测超时上限 */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { acl_int64 n = (timer->when - eventp->present) / 1000; if (n <= 0) delay = 0; else if ((int) n < delay) { delay = (int) n; if (delay <= 0) /* xxx */ delay = 100; } } /* 设置描述字对象的状态,添加/删除之前设置的描述字对象 */ event_set_all(eventp); if (eventp->fdcnt == 0) { if (eventp->fdcnt_ready == 0) sleep(1); goto TAG_DONE; } /* 如果已经有描述字准备好则检测超时时间置 0 */ if (eventp->fdcnt_ready > 0) delay = 0; /* 调用 epoll/kquque/devpoll 系统调用检测可用描述字 */ EVENT_BUFFER_READ(nready, ev->event_fd, ev->event_buf, ev->event_fdslots, delay); if (eventp->nested++ > 0) acl_msg_fatal("%s(%d): recursive call, nested: %d", myname, __LINE__, eventp->nested); if (nready < 0) { if (acl_last_error() != ACL_EINTR) { acl_msg_fatal("%s(%d), %s: select: %s", __FILE__, __LINE__, myname, acl_last_serror()); } goto TAG_DONE; } else if (nready == 0) goto TAG_DONE; /* 检查检测结果 */ for (bp = ev->event_buf; bp < ev->event_buf + nready; bp++) { #ifdef USE_FDMAP ACL_SOCKET sockfd; sockfd = EVENT_GET_FD(bp); fdp = acl_fdmap_ctx(ev->fdmap, sockfd); if (fdp == NULL || fdp->stream == NULL) continue; if (sockfd != ACL_VSTREAM_SOCK(fdp->stream)) acl_msg_fatal("%s(%d): sockfd(%d) != %d", myname, __LINE__, sockfd, ACL_VSTREAM_SOCK(fdp->stream)); #else fdp = (ACL_EVENT_FDTABLE *) EVENT_GET_CTX(bp); if (fdp == NULL || fdp->stream == NULL) continue; #endif /* 如果该描述字对象已经在被设置为异常或超时状态则继续 */ if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) continue; /* 检查描述字是否可读 */ if ((fdp->flag & EVENT_FDTABLE_FLAG_READ) && EVENT_TEST_READ(bp)) { /* 该描述字可读则设置 ACL_VSTREAM 的系统可读标志从而触发 * ACL_VSTREAM 流在读时调用系统的 read 函数 */ fdp->stream->sys_read_ready = 1; /* 给该描述字对象附加可读属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_READ; if (fdp->listener) fdp->event_type |= ACL_EVENT_ACCEPT; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp; } } /* 检查描述字是否可写 */ if ((fdp->flag & EVENT_FDTABLE_FLAG_WRITE) && EVENT_TEST_WRITE(bp)) { /* 给该描述字对象附加可写属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_WRITE; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp; } } #ifdef EVENT_TEST_ERROR if (EVENT_TEST_ERROR(bp)) { /* 如果出现异常则设置异常属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_XCPT; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp; } } #endif } TAG_DONE: /* * Deliver timer events. Requests are sorted: we can stop when we reach * the future or the list end. Allow the application to update the timer * queue while it is being called back. To this end, we repeatedly pop * the first request off the timer queue before delivering the event to * the application. */ /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); while ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { if (timer->when > eventp->present) break; timer_fn = timer->callback; timer_arg = timer->context; /* 定时器时间间隔 > 0 且允许定时器被循环调用,则重设定时器 */ if (timer->delay > 0 && timer->keep) { timer->ncount++; eventp->timer_request(eventp, timer->callback, timer->context, timer->delay, timer->keep); } else { acl_ring_detach(&timer->ring); /* first this */ timer->nrefer--; if (timer->nrefer != 0) acl_msg_fatal("%s(%d): nrefer(%d) != 0", myname, __LINE__, timer->nrefer); acl_myfree(timer); } timer_fn(ACL_EVENT_TIME, eventp, timer_arg); } /* 处理准备好的描述字事件 */ if (eventp->fdcnt_ready > 0) event_fire(eventp); eventp->nested--; }
static void event_loop(ACL_EVENT *eventp) { const char *myname = "event_loop"; EVENT_KERNEL *ev = (EVENT_KERNEL *) eventp; ACL_EVENT_NOTIFY_TIME timer_fn; void *timer_arg; ACL_EVENT_TIMER *timer; int delay; ACL_EVENT_FDTABLE *fdp; delay = (int) (eventp->delay_sec * 1000 + eventp->delay_usec / 1000); if (delay < 0) delay = 0; /* 0 milliseconds at least */ SET_TIME(eventp->present); /* * Find out when the next timer would go off. Timer requests are sorted. * If any timer is scheduled, adjust the delay appropriately. */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { acl_int64 n = (timer->when - eventp->present) / 1000; if (n <= 0) delay = 0; else if ((int) n < delay) delay = (int) n; } eventp->nested++; event_set_all(eventp); if (eventp->fdcnt == 0) { if (eventp->fdcnt_ready == 0) sleep(1); goto TAG_DONE; } if (eventp->fdcnt_ready > 0) delay = 0; TAG_DONE: /* * Deliver timer events. Requests are sorted: we can stop when we reach * the future or the list end. Allow the application to update the timer * queue while it is being called back. To this end, we repeatedly pop * the first request off the timer queue before delivering the event to * the application. */ SET_TIME(eventp->present); while ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { if (timer->when > eventp->present) break; timer_fn = timer->callback; timer_arg = timer->context; /* 如果定时器的时间间隔 > 0 且允许定时器被循环调用,则再重设定时器 */ if (timer->delay > 0 && timer->keep) { timer->ncount++; eventp->timer_request(eventp, timer->callback, timer->context, timer->delay, timer->keep); } else { acl_ring_detach(&timer->ring); /* first this */ timer->nrefer--; if (timer->nrefer != 0) acl_msg_fatal("%s(%d): nrefer(%d) != 0", myname, __LINE__, timer->nrefer); acl_myfree(timer); } timer_fn(ACL_EVENT_TIME, eventp, timer_arg); } for (;;) { BOOL isSuccess = FALSE; DWORD bytesTransferred = 0; DWORD iocpKey = 0; DWORD lastError = 0; IOCP_EVENT *iocp_event = NULL; isSuccess = GetQueuedCompletionStatus(ev->h_iocp, &bytesTransferred, (DWORD*) &fdp, (OVERLAPPED**) &iocp_event, delay); if (!isSuccess) { if (iocp_event == NULL) break; if (iocp_event->type == IOCP_EVENT_DEAD) acl_myfree(iocp_event); else if (iocp_event->fdp == NULL) { acl_msg_warn("%s(%d): fdp null", myname, __LINE__); acl_myfree(iocp_event); } else if (iocp_event->fdp != fdp) acl_msg_fatal("%s(%d): invalid fdp", myname, __LINE__); else if (!(fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) { fdp->event_type |= ACL_EVENT_XCPT; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp; eventp->fdcnt_ready++; } continue; } acl_assert(fdp == iocp_event->fdp); if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) { continue; } if (iocp_event->type == IOCP_EVENT_READ) { acl_assert(fdp->event_read == iocp_event); iocp_event->type &= ~IOCP_EVENT_READ; fdp->stream->sys_read_ready = 1; if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_READ; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp; eventp->fdcnt_ready++; } } if (iocp_event->type == IOCP_EVENT_WRITE) { acl_assert(fdp->event_write == iocp_event); iocp_event->type &= ~IOCP_EVENT_WRITE; if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_WRITE; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp; eventp->fdcnt_ready++; } } delay = 0; } if (eventp->fdcnt_ready > 0) event_fire(eventp); eventp->nested--; }