void XmlRpcDispatch::processFds (short revents, SourceList::iterator thisIt, XmlRpcSource *chunkWait) { XmlRpcSource* src = thisIt->getSource(); unsigned newMask = (unsigned) -1; // If you select on multiple event types this could be ambiguous try { if (revents & (POLLIN | POLLPRI)) newMask &= (src == chunkWait) ? src->handleChunkEvent(ReadableEvent) : src->handleEvent(ReadableEvent); } catch (const XmlRpcAsynchronous &async) { XmlRpcUtil::log(3, "Asynchronous event while handling response."); // stop monitoring the source.. thisIt->getMask() = 0; src->goAsync (); } if (revents & POLLOUT) newMask &= (src == chunkWait) ? src->handleChunkEvent(WritableEvent) : src->handleEvent(WritableEvent); if (revents & (POLLRDHUP | POLLERR | POLLHUP | POLLNVAL)) newMask &= (src == chunkWait) ? src->handleChunkEvent(Exception) : src->handleEvent(Exception); if ( ! newMask) { // Stop monitoring this one _sources.erase(thisIt); if ( ! src->getKeepOpen()) src->close(); } else if (newMask != (unsigned) -1) { thisIt->getMask() = newMask; } }
void XmlRpcDispatch::addToFd (void (*addFD) (int, short)) { SourceList::iterator it; for (it=_sources.begin(); it!=_sources.end(); ++it) { short events = 0; if (it->getMask() & ReadableEvent) events |= POLLIN | POLLPRI; if (it->getMask() & WritableEvent) events |= POLLOUT; if (it->getMask() & Exception) events |= POLLRDHUP | POLLERR | POLLHUP | POLLNVAL; if (events != 0) addFD (it->getSource()->getfd(), events); } }
void XmlRpcDispatch::addToFds (struct pollfd *fds, nfds_t &nfd) { SourceList::iterator it; for (it=_sources.begin(); it!=_sources.end(); ++it) { short events = 0; if (it->getMask() & ReadableEvent) events |= POLLIN | POLLPRI; if (it->getMask() & WritableEvent) events |= POLLOUT; if (it->getMask() & Exception) events |= POLLRDHUP | POLLERR | POLLHUP | POLLNVAL; if (events != 0) { fds[nfd].fd = it->getSource()->getfd(); fds[nfd].events = events; fds[nfd].revents = 0; nfd++; } } }
// Watch current set of sources and process events void XmlRpcDispatch::work(double timeout) { // Compute end time _endTime = (timeout < 0.0) ? -1.0 : (getTime() + timeout); _doClear = false; _inWork = true; // Only work while there is something to monitor while (_sources.size() > 0) { // Construct the sets of descriptors we are interested in fd_set inFd, outFd, excFd; FD_ZERO(&inFd); FD_ZERO(&outFd); FD_ZERO(&excFd); int maxFd = -1; // Not used on windows SourceList::iterator it; for (it=_sources.begin(); it!=_sources.end(); ++it) { int fd = it->getSource()->getfd(); if (it->getMask() & ReadableEvent) FD_SET(fd, &inFd); if (it->getMask() & WritableEvent) FD_SET(fd, &outFd); if (it->getMask() & Exception) FD_SET(fd, &excFd); if (it->getMask() && fd > maxFd) maxFd = fd; } // Check for events int nEvents; if (timeout < 0.0) nEvents = select(maxFd+1, &inFd, &outFd, &excFd, NULL); else { struct timeval tv; tv.tv_sec = (int)floor(timeout); tv.tv_usec = ((int)floor(1000000.0 * (timeout-floor(timeout)))) % 1000000; nEvents = select(maxFd+1, &inFd, &outFd, &excFd, &tv); } if (nEvents < 0) { XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); _inWork = false; return; } // Process events for (it=_sources.begin(); it != _sources.end(); ) { SourceList::iterator thisIt = it++; XmlRpcSource* src = thisIt->getSource(); int fd = src->getfd(); unsigned newMask = (unsigned) -1; if (fd <= maxFd) { // If you select on multiple event types this could be ambiguous if (FD_ISSET(fd, &inFd)) newMask &= src->handleEvent(ReadableEvent); if (FD_ISSET(fd, &outFd)) newMask &= src->handleEvent(WritableEvent); if (FD_ISSET(fd, &excFd)) newMask &= src->handleEvent(Exception); if ( ! newMask) { _sources.erase(thisIt); // Stop monitoring this one if ( ! src->getKeepOpen()) src->close(); } else if (newMask != (unsigned) -1) { thisIt->getMask() = newMask; } } } // Check whether to clear all sources if (_doClear) { SourceList closeList = _sources; _sources.clear(); for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { XmlRpcSource *src = it->getSource(); src->close(); } _doClear = false; } // Check whether end time has passed if (0 <= _endTime && getTime() > _endTime) break; } _inWork = false; }
// Watch current set of sources and process events void XmlRpcDispatch::work(double timeout_in_seconds) { // Compute end time _endTime = (timeout_in_seconds < 0.0) ? -1.0 : (getTime() + timeout_in_seconds); _doClear = false; _inWork = true; // Only work while there is something to monitor while (_sources.size() > 0) { // // Construct the sets of descriptors we are interested in // fd_set inFd, outFd, excFd; // FD_ZERO(&inFd); // FD_ZERO(&outFd); // FD_ZERO(&excFd); // int maxFd = -1; // Not used on windows // SourceList::iterator it; int fds_size = _sources.size(); std::vector<struct pollfd> fds(fds_size); { int __offset = 0; for (SourceList::iterator it=_sources.begin(); it!=_sources.end(); ++it) { fds[__offset].fd = it->getSource()->getfd(); fds[__offset].events = 0; fds[__offset].revents = 0; if (it->getMask() & ReadableEvent) fds[__offset].events |= POLLIN; if (it->getMask() & WritableEvent) fds[__offset].events |= POLLOUT; if (it->getMask() & Exception) fds[__offset].events |= POLLERR; // 2 if (it->getMask() && fd > maxFd) maxFd = fd; ++__offset; } } // Check for events returnhereoninterruptedsyscall: int nEvents; if (timeout_in_seconds < 0.0) nEvents = poll(&fds[0], fds_size, -1); else { nEvents = poll(&fds[0],fds_size, timeout_in_seconds * 1000); } if(nEvents == -1 and errno == EINTR) goto returnhereoninterruptedsyscall; if (nEvents < 0) { LOG_ERROR("Error in XmlRpcDispatch::work: error in select " << strerror(errno)); // LOG_ERROR(strerror(errno)); // XmlRpcUtil::error("Error in XmlRpcDispatch::work: error in select (%d).", nEvents); _inWork = false; return; } // Process events { size_t __offset = 0; for (SourceList::iterator it = _sources.begin(); it != _sources.end(); ) { SourceList::iterator thisIt = it++; XmlRpcSource* src = thisIt->getSource(); unsigned newMask = (unsigned) -1; // accepting a new connection (XmlRpcServer::handleEvent) // will add a new entry to _sources but we don't have an // entry in the fds around. if (__offset < fds.size()) { assert(fds[__offset].fd == src->getfd()); // if (fd <= maxFd) // { // If you select on multiple event types this could be ambiguous if (fds[__offset].revents bitand POLLIN) { newMask &= src->handleEvent(ReadableEvent); } if (fds[__offset].revents bitand POLLOUT) { newMask &= src->handleEvent(WritableEvent); } if (fds[__offset].revents bitand POLLERR) { newMask &= src->handleEvent(Exception); } } if (newMask == 0) { _sources.erase(thisIt); // Stop monitoring this one if (!src->getKeepOpen()) { src->close(); } } else if (newMask != (unsigned) -1) { thisIt->getMask() = newMask; } __offset++; } } // Check whether to clear all sources if (_doClear) { SourceList closeList = _sources; _sources.clear(); for (SourceList::iterator it=closeList.begin(); it!=closeList.end(); ++it) { XmlRpcSource *src = it->getSource(); src->close(); } _doClear = false; } // Check whether end time has passed if (0 <= _endTime && getTime() > _endTime) break; } _inWork = false; }