-#include "mplexer.hh"
-#include "sstuff.hh"
-#include <iostream>
-#include <unistd.h>
-#include "misc.hh"
-#include <boost/lexical_cast.hpp>
-#include "syncres.hh"
-
#if defined(__sun__) && defined(__svr4__)
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <port.h>
#include <sys/port_impl.h>
#endif
+#include <unistd.h>
+#include "mplexer.hh"
+#include "sstuff.hh"
+#include <iostream>
+
+#include "misc.hh"
-using namespace boost;
-using namespace std;
+#include "namespaces.hh"
class PortsFDMultiplexer : public FDMultiplexer
{
close(d_portfd);
}
- virtual int run(struct timeval* tv);
+ virtual int run(struct timeval* tv, int timeout=500);
- virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter);
+ virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd=nullptr);
virtual void removeFD(callbackmap_t& cbmap, int fd);
string getName()
{
throw FDMultiplexerException("Setting up port: "+stringerror());
}
-void PortsFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter)
+void PortsFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const boost::any& parameter, const struct timeval* ttd)
{
- accountingAddFD(cbmap, fd, toDo, parameter);
+ accountingAddFD(cbmap, fd, toDo, parameter, ttd);
if(port_associate(d_portfd, PORT_SOURCE_FD, fd, (&cbmap == &d_readCallbacks) ? POLLIN : POLLOUT, 0) < 0) {
cbmap.erase(fd);
void PortsFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
{
if(!cbmap.erase(fd))
- throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast<string>(fd)+ " from multiplexer");
+ throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
- if(port_dissociate(d_portfd, PORT_SOURCE_FD, fd) < 0)
+ if(port_dissociate(d_portfd, PORT_SOURCE_FD, fd) < 0 && errno != ENOENT) // it appears under some circumstances, ENOENT will be returned, without this being an error. Apache has this same "fix"
throw FDMultiplexerException("Removing fd from port set: "+stringerror());
}
-int PortsFDMultiplexer::run(struct timeval* now)
+int PortsFDMultiplexer::run(struct timeval* now, int timeout)
{
if(d_inrun) {
throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
}
- struct timespec timeout;
- timeout.tv_sec=0; timeout.tv_nsec=500000000;
+ struct timespec timeoutspec;
+ timeoutspec.tv_sec = time / 1000;
+ timeoutspec.tv_nsec = (time % 1000) * 1000000;
unsigned int numevents=1;
- int ret= port_getn(d_portfd, d_pevents.get(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeout);
-
- gettimeofday(now,0);
+ int ret= port_getn(d_portfd, d_pevents.get(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeoutspec);
- if(ret < 0) {
- if(errno!=EINTR && errno!=ETIME)
+ /* port_getn has an unusual API - (ret == -1, errno == ETIME) can
+ mean partial success; you must check (*numevents) in this case
+ and process anything in there, otherwise you'll never see any
+ events from that object again. We don't care about pure timeouts
+ (ret == -1, errno == ETIME, *numevents == 0) so we don't bother
+ with that case. */
+ if(ret == -1 && errno!=ETIME) {
+ if(errno!=EINTR)
throw FDMultiplexerException("completion port_getn returned error: "+stringerror());
- // EINTR and ETIME are not really errors
+ // EINTR is not really an error
+ gettimeofday(now,0);
return 0;
}
-
+ gettimeofday(now,0);
if(!numevents) // nothing
return 0;
d_iter=d_readCallbacks.find(d_pevents[n].portev_object);
if(d_iter != d_readCallbacks.end()) {
- d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
+ d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
if(d_readCallbacks.count(d_pevents[n].portev_object) && port_associate(d_portfd, PORT_SOURCE_FD, d_pevents[n].portev_object,
- POLLIN, 0) < 0)
- throw FDMultiplexerException("Unable to add fd back to ports (read): "+stringerror());
+ POLLIN, 0) < 0)
+ throw FDMultiplexerException("Unable to add fd back to ports (read): "+stringerror());
+ continue; // so we don't find ourselves as writable again
}
d_iter=d_writeCallbacks.find(d_pevents[n].portev_object);
if(d_iter != d_writeCallbacks.end()) {
- d_iter->second.d_callback(d_iter->first, d_iter->second.d_parameter);
+ d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
if(d_writeCallbacks.count(d_pevents[n].portev_object) && port_associate(d_portfd, PORT_SOURCE_FD, d_pevents[n].portev_object,
- POLLOUT, 0) < 0)
- throw FDMultiplexerException("Unable to add fd back to ports (write): "+stringerror());
+ POLLOUT, 0) < 0)
+ throw FDMultiplexerException("Unable to add fd back to ports (write): "+stringerror());
}
}
d_inrun=false;
- return 0;
+ return numevents;
}
#if 0
int main()
{
- Socket s(InterNetwork, Datagram);
+ Socket s(AF_INET, SOCK_DGRAM);
IPEndpoint loc("0.0.0.0", 2000);
s.bind(loc);