73 lines
1.6 KiB
C++
73 lines
1.6 KiB
C++
|
/**
|
||
|
* @file EventLoop.cpp
|
||
|
* @author apio (cloudapio.eu)
|
||
|
* @brief Base class for event-driven applications.
|
||
|
*
|
||
|
* @copyright Copyright (c) 2023, the Luna authors.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <errno.h>
|
||
|
#include <os/EventLoop.h>
|
||
|
#include <os/File.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
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<void> 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;
|
||
|
}
|
||
|
}
|