+ port_event_t& ev = events[i];
+
+ if (ev.portev_source != PORT_SOURCE_FD)
+ continue;
+
+ // Copy these in case the vector gets resized and ev invalidated
+ const int fd = ev.portev_object;
+ const int portev_events = ev.portev_events;
+ EventHandler* eh = static_cast<EventHandler*>(ev.portev_user);
+ if (eh->GetFd() < 0)
+ continue;
+
+ int mask = eh->GetEventMask();
+ if (portev_events & POLLWRNORM)
+ mask &= ~(FD_WRITE_WILL_BLOCK | FD_WANT_FAST_WRITE | FD_WANT_SINGLE_WRITE);
+ if (portev_events & POLLRDNORM)
+ mask &= ~FD_READ_WILL_BLOCK;
+ // reinsert port for next time around, pretending to be one-shot for writes
+ eh->SetEventMask(mask);
+ port_associate(EngineHandle, PORT_SOURCE_FD, fd, mask_to_events(mask), eh);
+ if (portev_events & POLLRDNORM)
+ {
+ stats.ReadEvents++;
+ eh->OnEventHandlerRead();
+ if (eh != GetRef(fd))
+ continue;
+ }
+ if (portev_events & POLLWRNORM)