terom@380: terom@380: #include "Reactor.hh" terom@380: terom@380: NetworkReactor::NetworkReactor (void) : terom@380: sockets() terom@380: { terom@380: terom@380: } terom@380: terom@380: void NetworkReactor::poll (timeval *timeout) { terom@384: int ret; terom@384: terom@400: // start counting the maximum fd from 0, select will be given nfds=1 if empty terom@380: int fd_max = 0; terom@380: terom@380: // zero our fdsets terom@380: fd_set read, write; terom@380: FD_ZERO(&read); terom@380: FD_ZERO(&write); terom@380: terom@380: // inspect our sockets terom@380: for (std::list::iterator it = sockets.begin(); it != sockets.end(); it++) { terom@380: NetworkSocket *socket = *it; terom@380: terom@380: // ask socket what events it wants terom@380: NetworkPollMask mask = socket->get_poll(); terom@380: terom@400: // ignore if nothing terom@380: if (mask) { terom@380: // socket file descriptor... terom@380: int fd = socket->get_socket(); terom@380: terom@380: // ignore invalid FDs terom@380: if (fd < 0) terom@380: continue; terom@380: terom@380: // update fd_max? terom@380: if (fd > fd_max) terom@380: fd_max = fd; terom@380: terom@380: // read... terom@380: if (mask & POLL_READ) terom@400: FD_SET(fd, &read); terom@380: terom@380: // write... terom@380: if (mask & POLL_WRITE) terom@400: FD_SET(fd, &write); terom@380: } terom@380: } terom@380: terom@384: // loop select() on EINTR terom@384: do { terom@384: // we never care about except, and pass NULL fdsets if they are empty terom@384: ret = select( terom@380: fd_max + 1, terom@380: fd_max ? &read : NULL, terom@380: fd_max ? &write : NULL, terom@380: NULL, terom@380: timeout terom@384: ); terom@384: } while (ret < 0 && errno == EINTR); terom@384: terom@384: // error? terom@384: if (ret < 0) terom@380: throw NetworkReactorError("select"); terom@380: terom@380: // ignore if we just timed out terom@380: if (ret == 0) terom@380: return; terom@380: terom@380: // notify up to socket-events terom@380: for (std::list::iterator it = sockets.begin(); it != sockets.end() && ret > 0; it++) { terom@380: NetworkSocket *socket = *it; terom@380: terom@380: // socket file descriptor... terom@380: int fd = socket->get_socket(); terom@380: terom@380: // ignore invalid FDs terom@380: if (fd < 0) terom@380: continue; terom@380: terom@380: // mask of events detected terom@380: NetworkPollMask mask = 0; terom@380: terom@380: // detect read terom@380: if (FD_ISSET(fd, &read)) { terom@380: mask |= POLL_READ; terom@380: ret--; terom@380: } terom@380: terom@380: // detect write terom@380: if (FD_ISSET(fd, &write)) { terom@380: mask |= POLL_WRITE; terom@380: ret--; terom@380: } terom@380: terom@380: // notify? terom@380: if (mask) terom@380: socket->notify(mask); terom@380: } terom@380: } terom@380: terom@380: // the global reactor terom@380: static NetworkReactor g_reactor; terom@380: NetworkReactor *NetworkReactor::current = &g_reactor; terom@380: