int PollEngine::DispatchEvents() { int i = poll(events, CurrentSetSize, 1000); int index; socklen_t codesize = sizeof(int); int errcode; int processed = 0; ServerInstance->UpdateTime(); if (i > 0) { for (index = 0; index < CurrentSetSize && processed != i; index++) { if (events[index].revents) processed++; EventHandler* eh = ref[index]; if (!eh) continue; if (events[index].revents & POLLHUP) { eh->HandleEvent(EVENT_ERROR, 0); continue; } if (events[index].revents & POLLERR) { // Get fd int fd = events[index].fd; // Get error number if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) errcode = errno; eh->HandleEvent(EVENT_ERROR, errcode); continue; } if (events[index].revents & POLLIN) { SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->HandleEvent(EVENT_READ); if (eh != ref[index]) // whoops, deleted out from under us continue; } if (events[index].revents & POLLOUT) { int mask = eh->GetEventMask(); mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE); SetEventMask(eh, mask); events[index].events = mask_to_poll(mask); eh->HandleEvent(EVENT_WRITE); } } } return i; }
int SocketEngine::DispatchEvents() { timeval tval; tval.tv_sec = 1; tval.tv_usec = 0; fd_set rfdset = ReadSet, wfdset = WriteSet, errfdset = ErrSet; int sresult = select(MaxFD + 1, &rfdset, &wfdset, &errfdset, &tval); ServerInstance->UpdateTime(); for (int i = 0, j = sresult; i <= MaxFD && j > 0; i++) { int has_read = FD_ISSET(i, &rfdset), has_write = FD_ISSET(i, &wfdset), has_error = FD_ISSET(i, &errfdset); if (!(has_read || has_write || has_error)) continue; --j; EventHandler* ev = GetRef(i); if (!ev) continue; if (has_error) { stats.ErrorEvents++; socklen_t codesize = sizeof(int); int errcode = 0; if (getsockopt(i, SOL_SOCKET, SO_ERROR, (char*)&errcode, &codesize) < 0) errcode = errno; ev->HandleEvent(EVENT_ERROR, errcode); continue; } if (has_read) { stats.ReadEvents++; ev->SetEventMask(ev->GetEventMask() & ~FD_READ_WILL_BLOCK); ev->HandleEvent(EVENT_READ); if (ev != GetRef(i)) continue; } if (has_write) { stats.WriteEvents++; int newmask = (ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE)); SocketEngine::OnSetEvent(ev, ev->GetEventMask(), newmask); ev->SetEventMask(newmask); ev->HandleEvent(EVENT_WRITE); } } return sresult; }
int SelectEngine::DispatchEvents() { static timeval tval = { 1, 0 }; fd_set rfdset = ReadSet, wfdset = WriteSet, errfdset = ErrSet; int sresult = select(MaxFD + 1, &rfdset, &wfdset, &errfdset, &tval); ServerInstance->UpdateTime(); /* Nothing to process this time around */ if (sresult < 1) return 0; for (int i = 0, j = sresult; i <= MaxFD && j > 0; i++) { int has_read = FD_ISSET(i, &rfdset), has_write = FD_ISSET(i, &wfdset), has_error = FD_ISSET(i, &errfdset); if (has_read || has_write || has_error) { --j; EventHandler* ev = ref[i]; if (!ev) continue; if (has_error) { ErrorEvents++; socklen_t codesize = sizeof(int); int errcode = 0; if (getsockopt(i, SOL_SOCKET, SO_ERROR, (char*)&errcode, &codesize) < 0) errcode = errno; ev->HandleEvent(EVENT_ERROR, errcode); continue; } if (has_read) { ReadEvents++; SetEventMask(ev, ev->GetEventMask() & ~FD_READ_WILL_BLOCK); ev->HandleEvent(EVENT_READ); if (ev != ref[i]) continue; } if (has_write) { WriteEvents++; SetEventMask(ev, ev->GetEventMask() & ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE)); ev->HandleEvent(EVENT_WRITE); } } } return sresult; }
int KQueueEngine::DispatchEvents() { ts.tv_nsec = 0; ts.tv_sec = 1; int i = kevent(EngineHandle, NULL, 0, &ke_list[0], ke_list.size(), &ts); ServerInstance->UpdateTime(); if (i < 0) return i; TotalEvents += i; for (int j = 0; j < i; j++) { struct kevent& kev = ke_list[j]; EventHandler* eh = GetRef(kev.ident); if (!eh) continue; if (kev.flags & EV_EOF) { ErrorEvents++; eh->HandleEvent(EVENT_ERROR, kev.fflags); continue; } if (kev.filter == EVFILT_WRITE) { WriteEvents++; /* When mask is FD_WANT_FAST_WRITE or FD_WANT_SINGLE_WRITE, * we set a one-shot write, so we need to clear that bit * to detect when it set again. */ const int bits_to_clr = FD_WANT_SINGLE_WRITE | FD_WANT_FAST_WRITE | FD_WRITE_WILL_BLOCK; SetEventMask(eh, eh->GetEventMask() & ~bits_to_clr); eh->HandleEvent(EVENT_WRITE); if (eh != GetRef(kev.ident)) // whoops, deleted out from under us continue; } if (kev.filter == EVFILT_READ) { ReadEvents++; SetEventMask(eh, eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->HandleEvent(EVENT_READ); } } return i; }
int PortsEngine::DispatchEvents() { struct timespec poll_time; poll_time.tv_sec = 1; poll_time.tv_nsec = 0; unsigned int nget = 1; // used to denote a retrieve request. int ret = port_getn(EngineHandle, this->events, GetMaxFds() - 1, &nget, &poll_time); ServerInstance->UpdateTime(); // first handle an error condition if (ret == -1) return -1; TotalEvents += nget; unsigned int i; for (i = 0; i < nget; i++) { switch (this->events[i].portev_source) { case PORT_SOURCE_FD: { int fd = this->events[i].portev_object; EventHandler* eh = ref[fd]; if (eh) { int mask = eh->GetEventMask(); if (events[i].portev_events & POLLWRNORM) mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE); if (events[i].portev_events & POLLRDNORM) mask &= ~FD_READ_WILL_BLOCK; // reinsert port for next time around, pretending to be one-shot for writes SetEventMask(eh, mask); port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh); if (events[i].portev_events & POLLRDNORM) { ReadEvents++; eh->HandleEvent(EVENT_READ); if (eh != ref[fd]) continue; } if (events[i].portev_events & POLLWRNORM) { WriteEvents++; eh->HandleEvent(EVENT_WRITE); } } } default: break; } } return (int)i; }
int EPollEngine::DispatchEvents() { socklen_t codesize = sizeof(int); int errcode; int i = epoll_wait(EngineHandle, events, GetMaxFds() - 1, 1000); ServerInstance->UpdateTime(); TotalEvents += i; for (int j = 0; j < i; j++) { EventHandler* eh = ref[events[j].data.fd]; if (!eh) { ServerInstance->Logs->Log("SOCKET",LOG_DEBUG,"Got event on unknown fd: %d", events[j].data.fd); epoll_ctl(EngineHandle, EPOLL_CTL_DEL, events[j].data.fd, &events[j]); continue; } if (events[j].events & EPOLLHUP) { ErrorEvents++; eh->HandleEvent(EVENT_ERROR, 0); continue; } if (events[j].events & EPOLLERR) { ErrorEvents++; /* Get error number */ if (getsockopt(events[j].data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) errcode = errno; eh->HandleEvent(EVENT_ERROR, errcode); continue; } int mask = eh->GetEventMask(); if (events[j].events & EPOLLIN) mask &= ~FD_READ_WILL_BLOCK; if (events[j].events & EPOLLOUT) { mask &= ~FD_WRITE_WILL_BLOCK; if (mask & FD_WANT_SINGLE_WRITE) { int nm = mask & ~FD_WANT_SINGLE_WRITE; OnSetEvent(eh, mask, nm); mask = nm; } } SetEventMask(eh, mask); if (events[j].events & EPOLLIN) { ReadEvents++; eh->HandleEvent(EVENT_READ); if (eh != ref[events[j].data.fd]) // whoa! we got deleted, better not give out the write event continue; } if (events[j].events & EPOLLOUT) { WriteEvents++; eh->HandleEvent(EVENT_WRITE); } } return i; }
int SocketEngine::DispatchEvents() { int i = poll(&events[0], CurrentSetSize, 1000); int processed = 0; ServerInstance->UpdateTime(); for (int index = 0; index < CurrentSetSize && processed < i; index++) { struct pollfd& pfd = events[index]; // Copy these in case the vector gets resized and pfd invalidated const int fd = pfd.fd; const short revents = pfd.revents; if (revents) processed++; EventHandler* eh = GetRef(fd); if (!eh) continue; if (revents & POLLHUP) { eh->HandleEvent(EVENT_ERROR, 0); continue; } if (revents & POLLERR) { // Get error number socklen_t codesize = sizeof(int); int errcode; if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) errcode = errno; eh->HandleEvent(EVENT_ERROR, errcode); continue; } if (revents & POLLIN) { eh->SetEventMask(eh->GetEventMask() & ~FD_READ_WILL_BLOCK); eh->HandleEvent(EVENT_READ); if (eh != GetRef(fd)) // whoops, deleted out from under us continue; } if (revents & POLLOUT) { int mask = eh->GetEventMask(); mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_SINGLE_WRITE); eh->SetEventMask(mask); // The vector could've been resized, reference can be invalid by now; don't use it events[index].events = mask_to_poll(mask); eh->HandleEvent(EVENT_WRITE); } } return i; }