]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Directly switch between read/write epoll states
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 15 Sep 2020 13:36:55 +0000 (15:36 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 10 Nov 2020 08:52:23 +0000 (09:52 +0100)
Altering an existing state instead of removing then adding it back
saves a call to `epoll_ctl()`.

pdns/epollmplexer.cc
pdns/mplexer.hh
pdns/pollmplexer.cc

index 433687d21456f8c24e7227683bb39bcdf719a04d..1a4b2a3b501ccbfb314b3661b3ee038db550cef6 100644 (file)
@@ -47,6 +47,8 @@ public:
 
   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";
@@ -91,7 +93,7 @@ EpollFDMultiplexer::EpollFDMultiplexer() : d_eevents(new epoll_event[s_maxevents
     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)
@@ -99,11 +101,11 @@ void EpollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo
   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);
@@ -113,8 +115,7 @@ void EpollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo
 
 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;
@@ -124,6 +125,22 @@ void EpollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
     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);
@@ -141,7 +158,7 @@ int EpollFDMultiplexer::run(struct timeval* now, int 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
 
@@ -154,13 +171,13 @@ int EpollFDMultiplexer::run(struct timeval* now, int timeout)
   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);
     }
@@ -184,7 +201,7 @@ void acceptData(int fd, funcparam_t& parameter)
 int main()
 {
   Socket s(AF_INET, SOCK_DGRAM);
-  
+
   IPEndpoint loc("0.0.0.0", 2000);
   s.bind(loc);
 
@@ -199,5 +216,3 @@ int main()
   sfm.removeReadFD(s.getHandle());
 }
 #endif
-
-
index a2cd0b75075d80d23c2ba9a6d394cd35e36a1086..a948c9f075be8f9a548bcff590c2297d41e13136 100644 (file)
@@ -136,6 +136,16 @@ public:
     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;
@@ -209,6 +219,7 @@ protected:
 
   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;
 
@@ -223,7 +234,7 @@ protected:
       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");
     }
@@ -235,4 +246,12 @@ protected:
       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);
+  }
+
 };
index 399ad132ae8a3bd6dca4d566d2ed03fa952584e4..665b4b823c8a9788a391fc8bc77ab58c978f5761 100644 (file)
@@ -70,8 +70,7 @@ void PollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
   if(d_inrun && d_iter->d_fd==fd)  // trying to remove us!
     ++d_iter;
 
-  if(!cbmap.erase(fd))
-    throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
+  accountingRemoveFD(cbmap, fd);
 }
 
 vector<struct pollfd> PollFDMultiplexer::preparePollFD() const