Commit b569240a authored by louiz’'s avatar louiz’

Use epoll

parent 1e122d33
...@@ -12,6 +12,13 @@ Poller::Poller() ...@@ -12,6 +12,13 @@ Poller::Poller()
#if POLLER == POLL #if POLLER == POLL
memset(this->fds, 0, sizeof(this->fds)); memset(this->fds, 0, sizeof(this->fds));
this->nfds = 0; 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 #endif
} }
...@@ -36,6 +43,17 @@ void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler) ...@@ -36,6 +43,17 @@ void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler)
this->fds[this->nfds].events = POLLIN; this->fds[this->nfds].events = POLLIN;
this->nfds++; this->nfds++;
#endif #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) void Poller::remove_socket_handler(const socket_t socket)
...@@ -44,6 +62,8 @@ 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()) if (it == this->socket_handlers.end())
throw std::runtime_error("Trying to remove a SocketHandler that is not managed"); throw std::runtime_error("Trying to remove a SocketHandler that is not managed");
this->socket_handlers.erase(it); this->socket_handlers.erase(it);
#if POLLER == POLL
for (size_t i = 0; i < this->nfds; i++) for (size_t i = 0; i < this->nfds; i++)
{ {
if (this->fds[i].fd == socket) if (this->fds[i].fd == socket)
...@@ -58,9 +78,17 @@ void Poller::remove_socket_handler(const socket_t socket) ...@@ -58,9 +78,17 @@ void Poller::remove_socket_handler(const socket_t socket)
this->nfds--; 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 #if POLLER == POLL
for (size_t i = 0; i <= this->nfds; ++i) for (size_t i = 0; i <= this->nfds; ++i)
...@@ -71,11 +99,21 @@ void Poller::watch_send_events(const SocketHandler* const socket_handler) ...@@ -71,11 +99,21 @@ void Poller::watch_send_events(const SocketHandler* const socket_handler)
return; return;
} }
} }
#endif
throw std::runtime_error("Cannot watch a non-registered socket for send events"); 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 #if POLLER == POLL
for (size_t i = 0; i <= this->nfds; ++i) for (size_t i = 0; i <= this->nfds; ++i)
...@@ -86,8 +124,18 @@ void Poller::stop_watching_send_events(const SocketHandler* const socket_handler ...@@ -86,8 +124,18 @@ void Poller::stop_watching_send_events(const SocketHandler* const socket_handler
return; return;
} }
} }
#endif
throw std::runtime_error("Cannot watch a non-registered socket for send events"); 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() bool Poller::poll()
...@@ -121,6 +169,23 @@ bool Poller::poll() ...@@ -121,6 +169,23 @@ bool Poller::poll()
res--; 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 #endif
return true; return true;
} }
...@@ -10,26 +10,28 @@ ...@@ -10,26 +10,28 @@
#define EPOLL 2 #define EPOLL 2
#define KQUEUE 3 #define KQUEUE 3
#define POLLER POLL #include <config.h>
#ifndef POLLER
// Default standard poller
#define POLLER EPOLL
#endif
#if POLLER == POLL #if POLLER == POLL
#include <poll.h> #include <poll.h>
// TODO, dynamic size, without artificial limit
#define MAX_POLL_FD_NUMBER 4096 #define MAX_POLL_FD_NUMBER 4096
#elif POLLER == EPOLL
#include <sys/epoll.h>
#endif #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, * poll/epoll/kqueue/select etc to wait for events on these SocketHandlers,
* and call the callbacks when event occurs. * and call the callbacks when event occurs.
* *
* TODO: support for all these pollers: * TODO: support these pollers:
* - poll(2) (mandatory)
* - epoll(7)
* - kqueue(2) * - kqueue(2)
*/ */
class Poller class Poller
{ {
public: public:
...@@ -48,12 +50,12 @@ public: ...@@ -48,12 +50,12 @@ public:
* Signal the poller that he needs to watch for send events for the given * Signal the poller that he needs to watch for send events for the given
* SocketHandler. * 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 * Signal the poller that he needs to stop watching for send events for
* this SocketHandler. * 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 * Wait for all watched events, and call the SocketHandlers' callbacks
* when one is ready. * when one is ready.
...@@ -72,6 +74,8 @@ private: ...@@ -72,6 +74,8 @@ private:
#if POLLER == POLL #if POLLER == POLL
struct pollfd fds[MAX_POLL_FD_NUMBER]; struct pollfd fds[MAX_POLL_FD_NUMBER];
nfds_t nfds; nfds_t nfds;
#elif POLLER == EPOLL
int epfd;
#endif #endif
Poller(const Poller&) = delete; Poller(const Poller&) = delete;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment