/** * @file EventLoop.cpp * @author apio (cloudapio.eu) * @brief Base class for event-driven applications. * * @copyright Copyright (c) 2023, the Luna authors. * */ #include #include #include #include static os::EventLoop* s_the = nullptr; namespace os { EventLoop::EventLoop() { s_the = this; } EventLoop::~EventLoop() { s_the = nullptr; } EventLoop& EventLoop::the() { check(s_the); return *s_the; } Result EventLoop::register_fd_listener(int fd, void (*listener)(int, int)) { TRY(m_fd_listeners.try_set(fd, listener)); TRY(m_pollfds.try_append({ .fd = fd, .events = POLLIN, .revents = 0 })); return {}; } int EventLoop::run() { while (!m_should_quit) { for (auto& pfd : m_pollfds) { pfd.revents = 0; } int rc = poll(m_pollfds.data(), m_pollfds.size(), 1000); if (!rc) continue; if (rc < 0 && errno != EINTR) { os::println("poll: error: %s", strerror(errno)); return 1; } for (usize i = 0; i < m_fd_listeners.size(); i++) { if (m_pollfds[i].revents) m_fd_listeners.try_get(m_pollfds[i].fd) .value()(m_pollfds[i].fd, m_pollfds[i].revents); // Invoke the callback } } return m_quit_status; } void EventLoop::quit(int status) { m_quit_status = status; m_should_quit = true; } }