summaryrefslogtreecommitdiff
path: root/src/network/poller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/poller.cpp')
-rw-r--r--src/network/poller.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/network/poller.cpp b/src/network/poller.cpp
new file mode 100644
index 0000000..c7d9eb2
--- /dev/null
+++ b/src/network/poller.cpp
@@ -0,0 +1,96 @@
+#include <network/poller.hpp>
+
+#include <assert.h>
+#include <cstring>
+#include <iostream>
+
+
+Poller::Poller()
+{
+ std::cout << "Poller()" << std::endl;
+#if POLLER == POLL
+ memset(this->fds, 0, sizeof(this->fds));
+ this->nfds = 0;
+#endif
+}
+
+Poller::~Poller()
+{
+ std::cout << "~Poller()" << std::endl;
+}
+
+void Poller::add_socket_handler(std::shared_ptr<SocketHandler> socket_handler)
+{
+ // Raise an error if that socket is already in the list
+ const auto it = this->socket_handlers.find(socket_handler->get_socket());
+ if (it != this->socket_handlers.end())
+ throw std::runtime_error("Trying to insert SocketHandler already managed");
+
+ this->socket_handlers.emplace(socket_handler->get_socket(), socket_handler);
+ socket_handler->set_poller(this);
+
+ // We always watch all sockets for receive events
+#if POLLER == POLL
+ this->fds[this->nfds].fd = socket_handler->get_socket();
+ this->fds[this->nfds].events = POLLIN;
+ this->nfds++;
+#endif
+}
+
+void Poller::remove_socket_handler(const socket_t socket)
+{
+ const auto it = this->socket_handlers.find(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);
+ for (size_t i = 0; i < this->nfds; i++)
+ {
+ if (this->fds[i].fd == socket)
+ {
+ // Move all subsequent pollfd by one on the left, erasing the
+ // value of the one we remove
+ for (size_t j = i; j < this->nfds - 1; ++j)
+ {
+ this->fds[j].fd = this->fds[j+1].fd;
+ this->fds[j].events= this->fds[j+1].events;
+ }
+ this->nfds--;
+ }
+ }
+}
+
+void Poller::poll()
+{
+#if POLLER == POLL
+ std::cout << "Polling:" << std::endl;
+ for (size_t i = 0; i < this->nfds; ++i)
+ std::cout << "pollfd[" << i << "]: (" << this->fds[i].fd << ")" << std::endl;
+ int res = ::poll(this->fds, this->nfds, -1);
+ if (res < 0)
+ {
+ perror("poll");
+ throw std::runtime_error("Poll failed");
+ }
+ // We cannot possibly have more ready events than the number of fds we are
+ // watching
+ assert(static_cast<unsigned int>(res) <= this->nfds);
+ for (size_t i = 0; i <= this->nfds && res != 0; ++i)
+ {
+ if (this->fds[i].revents == 0)
+ continue;
+ else if (this->fds[i].revents & POLLIN)
+ {
+ auto socket_handler = this->socket_handlers.at(this->fds[i].fd);
+ socket_handler->on_recv();
+ res--;
+ }
+ else if (this->fds[i].revents & POLLOUT)
+ {
+ auto socket_handler = this->socket_handlers.at(this->fds[i].fd);
+ socket_handler->on_send();
+ res--;
+ }
+ }
+#endif
+}
+