From b569240a55a0df3a78d3cb3e1e673e9347e531c0 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 17 Nov 2013 12:55:45 +0100 Subject: Use epoll --- src/network/poller.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++--- src/network/poller.hpp | 22 ++++++++------- 2 files changed, 82 insertions(+), 13 deletions(-) (limited to 'src/network') diff --git a/src/network/poller.cpp b/src/network/poller.cpp index e790e60..023fb12 100644 --- a/src/network/poller.cpp +++ b/src/network/poller.cpp @@ -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 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(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; } diff --git a/src/network/poller.hpp b/src/network/poller.hpp index 319236b..e6ce7f2 100644 --- a/src/network/poller.hpp +++ b/src/network/poller.hpp @@ -10,26 +10,28 @@ #define EPOLL 2 #define KQUEUE 3 -#define POLLER POLL +#include +#ifndef POLLER + // Default standard poller + #define POLLER EPOLL +#endif #if POLLER == POLL #include - // TODO, dynamic size, without artificial limit #define MAX_POLL_FD_NUMBER 4096 +#elif POLLER == EPOLL + #include #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; -- cgit v1.2.3