virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override;
virtual void removeFD(callbackmap_t& cbmap, int fd) override;
+ virtual void alterFD(callbackmap_t& from, callbackmap_t& to, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd) override;
+
string getName() const override
{
return "epoll";
close(d_epollfd);
throw FDMultiplexerException("epoll multiplexer failed self-test: "+string(fe.what()));
}
-
+
}
void EpollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd)
accountingAddFD(cbmap, fd, toDo, parameter, ttd);
struct epoll_event eevent;
-
+
eevent.events = (&cbmap == &d_readCallbacks) ? EPOLLIN : EPOLLOUT;
-
+
eevent.data.u64=0; // placate valgrind (I love it so much)
- eevent.data.fd=fd;
+ eevent.data.fd=fd;
if(epoll_ctl(d_epollfd, EPOLL_CTL_ADD, fd, &eevent) < 0) {
cbmap.erase(fd);
void EpollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
{
- if(!cbmap.erase(fd))
- throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
+ accountingRemoveFD(cbmap, fd);
struct epoll_event dummy;
dummy.events = 0;
throw FDMultiplexerException("Removing fd from epoll set: "+stringerror());
}
+void EpollFDMultiplexer::alterFD(callbackmap_t& from, callbackmap_t& to, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd)
+{
+ accountingRemoveFD(from, fd);
+ accountingAddFD(to, fd, toDo, parameter, ttd);
+
+ struct epoll_event eevent;
+ eevent.events = (&to == &d_readCallbacks) ? EPOLLIN : EPOLLOUT;
+ eevent.data.u64 = 0; // placate valgrind (I love it so much)
+ eevent.data.fd = fd;
+
+ if (epoll_ctl(d_epollfd, EPOLL_CTL_MOD, fd, &eevent) < 0) {
+ to.erase(fd);
+ throw FDMultiplexerException("Altering fd in epoll set: "+stringerror());
+ }
+}
+
void EpollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
{
int ret=epoll_wait(d_epollfd, d_eevents.get(), s_maxevents, timeout);
if(d_inrun) {
throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
}
-
+
int ret=epoll_wait(d_epollfd, d_eevents.get(), s_maxevents, timeout);
gettimeofday(now,0); // MANDATORY
d_inrun=true;
for(int n=0; n < ret; ++n) {
d_iter=d_readCallbacks.find(d_eevents[n].data.fd);
-
+
if(d_iter != d_readCallbacks.end()) {
d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
continue; // so we don't refind ourselves as writable!
}
d_iter=d_writeCallbacks.find(d_eevents[n].data.fd);
-
+
if(d_iter != d_writeCallbacks.end()) {
d_iter->d_callback(d_iter->d_fd, d_iter->d_parameter);
}
int main()
{
Socket s(AF_INET, SOCK_DGRAM);
-
+
IPEndpoint loc("0.0.0.0", 2000);
s.bind(loc);
sfm.removeReadFD(s.getHandle());
}
#endif
-
-
d_writeCallbacks.replace(it, newEntry);
}
+ virtual void alterFDToRead(int fd, callbackfunc_t toDo, const funcparam_t& parameter=funcparam_t(), const struct timeval* ttd=nullptr)
+ {
+ this->alterFD(d_writeCallbacks, d_readCallbacks, fd, toDo, parameter, ttd);
+ }
+
+ virtual void alterFDToWrite(int fd, callbackfunc_t toDo, const funcparam_t& parameter=funcparam_t(), const struct timeval* ttd=nullptr)
+ {
+ this->alterFD(d_readCallbacks, d_writeCallbacks, fd, toDo, parameter, ttd);
+ }
+
virtual std::vector<std::pair<int, funcparam_t> > getTimeouts(const struct timeval& tv, bool writes=false)
{
std::vector<std::pair<int, funcparam_t> > ret;
virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr)=0;
virtual void removeFD(callbackmap_t& cbmap, int fd)=0;
+
bool d_inrun;
callbackmap_t::iterator d_iter;
cb.d_ttd = *ttd;
}
- auto pair = cbmap.insert(cb);
+ auto pair = cbmap.insert(std::move(cb));
if (!pair.second) {
throw FDMultiplexerException("Tried to add fd "+std::to_string(fd)+ " to multiplexer twice");
}
throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
}
}
+
+ virtual void alterFD(callbackmap_t& from, callbackmap_t& to, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd)
+ {
+ /* naive implementation */
+ removeFD(from, fd);
+ addFD(to, fd, toDo, parameter, ttd);
+ }
+
};