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 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; }