~singpolyma/biboumi

b569240a55a0df3a78d3cb3e1e673e9347e531c0 — Florent Le Coz 10 years ago 1e122d3
Use epoll
2 files changed, 82 insertions(+), 13 deletions(-)

M src/network/poller.cpp
M src/network/poller.hpp
M src/network/poller.cpp => src/network/poller.cpp +69 -4
@@ 12,6 12,13 @@ Poller::Poller()
#if POLLER == POLL
  memset(this->fds, 0, sizeof(this->fds));
  this->nfds = 0;
#elif POLLER == EPOLL
  this->epfd = ::epoll_create1(0);
  if (this->epfd == -1)
    {
      perror("epoll");
      throw std::runtime_error("Could not create epoll instance");
    }
#endif
}



@@ 36,6 43,17 @@ void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler)
  this->fds[this->nfds].events = POLLIN;
  this->nfds++;
#endif
#if POLLER == EPOLL
  struct epoll_event event;
  event.data.ptr = socket_handler.get();
  event.events = EPOLLIN;
  const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_ADD, socket_handler->get_socket(), &event);
  if (res == -1)
    {
      perror("epoll_ctl");
      throw std::runtime_error("Could not add socket to epoll");
    }
#endif
}

void Poller::remove_socket_handler(const socket_t socket)


@@ 44,6 62,8 @@ void Poller::remove_socket_handler(const socket_t socket)
  if (it == this->socket_handlers.end())
    throw std::runtime_error("Trying to remove a SocketHandler that is not managed");
  this->socket_handlers.erase(it);

#if POLLER == POLL
  for (size_t i = 0; i < this->nfds; i++)
    {
      if (this->fds[i].fd == socket)


@@ 58,9 78,17 @@ void Poller::remove_socket_handler(const socket_t socket)
          this->nfds--;
        }
    }
#elif POLLER == EPOLL
  const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_DEL, socket, nullptr);
  if (res == -1)
    {
      perror("epoll_ctl");
      throw std::runtime_error("Could not remove socket from epoll");
    }
#endif
}

void Poller::watch_send_events(const SocketHandler* const socket_handler)
void Poller::watch_send_events(SocketHandler* socket_handler)
{
#if POLLER == POLL
  for (size_t i = 0; i <= this->nfds; ++i)


@@ 71,11 99,21 @@ void Poller::watch_send_events(const SocketHandler* const socket_handler)
          return;
        }
    }
#endif
  throw std::runtime_error("Cannot watch a non-registered socket for send events");
#elif POLLER == EPOLL
  struct epoll_event event;
  event.data.ptr = socket_handler;
  event.events = EPOLLIN|EPOLLOUT;
  const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event);
  if (res == -1)
    {
      perror("epoll_ctl");
      throw std::runtime_error("Could not modify socket flags in epoll");
    }
#endif
}

void Poller::stop_watching_send_events(const SocketHandler* const socket_handler)
void Poller::stop_watching_send_events(SocketHandler* socket_handler)
{
#if POLLER == POLL
  for (size_t i = 0; i <= this->nfds; ++i)


@@ 86,8 124,18 @@ void Poller::stop_watching_send_events(const SocketHandler* const socket_handler
          return;
        }
    }
#endif
  throw std::runtime_error("Cannot watch a non-registered socket for send events");
#elif POLLER == EPOLL
  struct epoll_event event;
  event.data.ptr = socket_handler;
  event.events = EPOLLIN;
  const int res = ::epoll_ctl(this->epfd, EPOLL_CTL_MOD, socket_handler->get_socket(), &event);
  if (res == -1)
    {
      perror("epoll_ctl");
      throw std::runtime_error("Could not modify socket flags in epoll");
    }
#endif
}

bool Poller::poll()


@@ 121,6 169,23 @@ bool Poller::poll()
          res--;
        }
    }
#elif POLLER == EPOLL
  static const size_t max_events = 12;
  struct epoll_event revents[max_events];
  const int nb_events = epoll_wait(this->epfd, revents, max_events, -1);
  if (nb_events == -1)
    {
      perror("epoll_wait");
      throw std::runtime_error("Epoll_wait failed");
    }
  for (int i = 0; i < nb_events; ++i)
    {
      auto socket_handler = static_cast<SocketHandler*>(revents[i].data.ptr);
      if (revents[i].events & EPOLLIN)
        socket_handler->on_recv();
      if (revents[i].events & EPOLLOUT)
        socket_handler->on_send();
    }
#endif
  return true;
}

M src/network/poller.hpp => src/network/poller.hpp +13 -9
@@ 10,26 10,28 @@
#define EPOLL 2
#define KQUEUE 3

#define POLLER POLL
#include <config.h>
#ifndef POLLER
  // Default standard poller
  #define POLLER EPOLL
#endif

#if POLLER == POLL
 #include <poll.h>
 // TODO, dynamic size, without artificial limit
 #define MAX_POLL_FD_NUMBER 4096
#elif POLLER == EPOLL
  #include <sys/epoll.h>
#endif

/**
 * We pass some SocketHandlers to this the Poller, which uses
 * We pass some SocketHandlers to this Poller, which uses
 * poll/epoll/kqueue/select etc to wait for events on these SocketHandlers,
 * and call the callbacks when event occurs.
 *
 * TODO: support for all these pollers:
 * - poll(2) (mandatory)
 * - epoll(7)
 * TODO: support these pollers:
 * - kqueue(2)
 */


class Poller
{
public:


@@ 48,12 50,12 @@ public:
   * Signal the poller that he needs to watch for send events for the given
   * SocketHandler.
   */
  void watch_send_events(const SocketHandler* const socket_handler);
  void watch_send_events(SocketHandler* socket_handler);
  /**
   * Signal the poller that he needs to stop watching for send events for
   * this SocketHandler.
   */
  void stop_watching_send_events(const SocketHandler* const socket_handler);
  void stop_watching_send_events(SocketHandler* socket_handler);
  /**
   * Wait for all watched events, and call the SocketHandlers' callbacks
   * when one is ready.


@@ 72,6 74,8 @@ private:
#if POLLER == POLL
  struct pollfd fds[MAX_POLL_FD_NUMBER];
  nfds_t nfds;
#elif POLLER == EPOLL
  int epfd;
#endif

  Poller(const Poller&) = delete;