int d_devpollfd;
};
-static FDMultiplexer* makeDevPoll()
+static FDMultiplexer* makeDevPoll(unsigned int)
{
return new DevPollFDMultiplexer();
}
class EpollFDMultiplexer : public FDMultiplexer
{
public:
- EpollFDMultiplexer();
+ EpollFDMultiplexer(unsigned int maxEventsHint);
~EpollFDMultiplexer()
{
if (d_epollfd >= 0) {
private:
int d_epollfd;
std::vector<epoll_event> d_eevents;
- static int s_maxevents; // not a hard maximum
};
-static FDMultiplexer* makeEpoll()
+static FDMultiplexer* makeEpoll(unsigned int maxEventsHint)
{
- return new EpollFDMultiplexer();
+ return new EpollFDMultiplexer(maxEventsHint);
}
static struct EpollRegisterOurselves
}
} doItEpoll;
-int EpollFDMultiplexer::s_maxevents = 1024;
-
-EpollFDMultiplexer::EpollFDMultiplexer() :
- d_eevents(s_maxevents)
+EpollFDMultiplexer::EpollFDMultiplexer(unsigned int maxEventsHint) :
+ d_eevents(maxEventsHint)
{
- d_epollfd = epoll_create(s_maxevents); // not hard max
+ d_epollfd = epoll_create(static_cast<int>(maxEventsHint)); // not hard max, just a hint that is actually ignored since Linux 2.6.8
if (d_epollfd < 0) {
throw FDMultiplexerException("Setting up epoll: " + stringerror());
}
void EpollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
{
- int ret = epoll_wait(d_epollfd, d_eevents.data(), s_maxevents, timeout);
+ int ret = epoll_wait(d_epollfd, d_eevents.data(), d_eevents.size(), timeout);
if (ret < 0 && errno != EINTR) {
throw FDMultiplexerException("epoll returned error: " + stringerror());
throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
}
- int ret = epoll_wait(d_epollfd, d_eevents.data(), s_maxevents, timeout);
+ int ret = epoll_wait(d_epollfd, d_eevents.data(), d_eevents.size(), timeout);
gettimeofday(now, nullptr); // MANDATORY
if (ret < 0 && errno != EINTR) {
class KqueueFDMultiplexer : public FDMultiplexer
{
public:
- KqueueFDMultiplexer();
+ KqueueFDMultiplexer(unsigned int maxEventsHint);
~KqueueFDMultiplexer()
{
if (d_kqueuefd >= 0) {
private:
int d_kqueuefd;
std::vector<struct kevent> d_kevents;
- static unsigned int s_maxevents; // not a hard maximum
};
-unsigned int KqueueFDMultiplexer::s_maxevents = 1024;
-
-static FDMultiplexer* make()
+static FDMultiplexer* make(unsigned int maxEventsHint)
{
- return new KqueueFDMultiplexer();
+ return new KqueueFDMultiplexer(maxEventsHint);
}
static struct KqueueRegisterOurselves
}
} kQueueDoIt;
-KqueueFDMultiplexer::KqueueFDMultiplexer() :
- d_kevents(s_maxevents)
+KqueueFDMultiplexer::KqueueFDMultiplexer(unsigned int maxEventsHint) :
+ d_kevents(maxEventsHint)
{
d_kqueuefd = kqueue();
if (d_kqueuefd < 0) {
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000;
- int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), s_maxevents, &ts);
+ int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), &ts);
if (ret < 0 && errno != EINTR) {
throw FDMultiplexerException("kqueue returned error: " + stringerror());
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000;
- int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), s_maxevents, &ts);
+ int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), &ts);
gettimeofday(now, nullptr); // MANDATORY!
if (ret < 0 && errno != EINTR) {
virtual ~FDMultiplexer()
{}
- static FDMultiplexer* getMultiplexerSilent();
+ // The maximum number of events processed in a single run, not the maximum of watched descriptors
+ static constexpr unsigned int s_maxevents = 1024;
+ /* The maximum number of events processed in a single run will be capped to the
+ minimum value of maxEventsHint and s_maxevents, to reduce memory usage. */
+ static FDMultiplexer* getMultiplexerSilent(unsigned int maxEventsHint = s_maxevents);
/* tv will be updated to 'now' before run returns */
/* timeout is in ms */
return ret;
}
- typedef FDMultiplexer* getMultiplexer_t();
+ typedef FDMultiplexer* getMultiplexer_t(unsigned int);
typedef std::multimap<int, getMultiplexer_t*> FDMultiplexermap_t;
static FDMultiplexermap_t& getMultiplexerMap()
#include "misc.hh"
#include "namespaces.hh"
-FDMultiplexer* FDMultiplexer::getMultiplexerSilent()
+FDMultiplexer* FDMultiplexer::getMultiplexerSilent(unsigned int maxEventsHint)
{
FDMultiplexer* ret = nullptr;
for (const auto& i : FDMultiplexer::getMultiplexerMap()) {
try {
- ret = i.second();
+ ret = i.second(std::min(maxEventsHint, FDMultiplexer::s_maxevents));
return ret;
}
catch (const FDMultiplexerException& fe) {
class PollFDMultiplexer : public FDMultiplexer
{
public:
- PollFDMultiplexer()
+ PollFDMultiplexer(unsigned int maxEventsHint)
{}
~PollFDMultiplexer()
{
vector<struct pollfd> preparePollFD() const;
};
-static FDMultiplexer* make()
+static FDMultiplexer* make(unsigned int maxEventsHint)
{
- return new PollFDMultiplexer();
+ return new PollFDMultiplexer(maxEventsHint);
}
static struct RegisterOurselves
class PortsFDMultiplexer : public FDMultiplexer
{
public:
- PortsFDMultiplexer();
+ PortsFDMultiplexer(unsigned int maxEventsHint);
~PortsFDMultiplexer()
{
close(d_portfd);
private:
int d_portfd;
std::vector<port_event_t> d_pevents;
- static int s_maxevents; // not a hard maximum
};
-static FDMultiplexer* makePorts()
+static FDMultiplexer* makePorts(unsigned int)
{
return new PortsFDMultiplexer();
}
}
} doItPorts;
-int PortsFDMultiplexer::s_maxevents = 1024;
-
-PortsFDMultiplexer::PortsFDMultiplexer() :
- d_pevents(s_maxevents)
+PortsFDMultiplexer::PortsFDMultiplexer(unsigned int maxEventsHint) :
+ d_pevents(maxEventsHint)
{
d_portfd = port_create(); // not hard max
if (d_portfd < 0) {
timeoutspec.tv_sec = timeout / 1000;
timeoutspec.tv_nsec = (timeout % 1000) * 1000000;
unsigned int numevents = 1;
- int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeoutspec);
+ int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, d_pevents.size()), &numevents, &timeoutspec);
/* port_getn has an unusual API - (ret == -1, errno == ETIME) can
mean partial success; you must check (*numevents) in this case
timeoutspec.tv_sec = timeout / 1000;
timeoutspec.tv_nsec = (timeout % 1000) * 1000000;
unsigned int numevents = 1;
- int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeoutspec);
+ int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, d_pevents.size()), &numevents, &timeoutspec);
/* port_getn has an unusual API - (ret == -1, errno == ETIME) can
mean partial success; you must check (*numevents) in this case
FDMultiplexer* ret;
for (const auto& i : FDMultiplexer::getMultiplexerMap()) {
try {
- ret = i.second();
+ ret = i.second(FDMultiplexer::s_maxevents);
return ret;
}
catch (FDMultiplexerException& fe) {
BOOST_AUTO_TEST_CASE(test_MPlexer)
{
for (const auto& entry : FDMultiplexer::getMultiplexerMap()) {
- auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second());
+ auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second(FDMultiplexer::s_maxevents));
BOOST_REQUIRE(mplexer != nullptr);
//cerr<<"Testing multiplexer "<<mplexer->getName()<<endl;
BOOST_AUTO_TEST_CASE(test_MPlexer_ReadAndWrite)
{
for (const auto& entry : FDMultiplexer::getMultiplexerMap()) {
- auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second());
+ auto mplexer = std::unique_ptr<FDMultiplexer>(entry.second(FDMultiplexer::s_maxevents));
BOOST_REQUIRE(mplexer != nullptr);
//cerr<<"Testing multiplexer "<<mplexer->getName()<<" for read AND write"<<endl;