Luna/libos/include/os/EventLoop.h

97 lines
2.8 KiB
C++

/**
* @file EventLoop.h
* @author apio (cloudapio.eu)
* @brief Base class for event-driven applications.
*
* @copyright Copyright (c) 2023-2024, the Luna authors.
*
*/
#pragma once
#include <luna/HashMap.h>
#include <luna/Vector.h>
#include <os/Action.h>
#include <os/Timer.h>
#include <sys/poll.h>
namespace os
{
/**
* @brief Event loop implementation.
*/
class EventLoop
{
public:
/**
* @brief Construct a new event loop, which will automatically register itself as the current global event loop.
*/
EventLoop();
~EventLoop();
EventLoop(EventLoop&&) = delete;
EventLoop(const EventLoop&) = delete;
/**
* @brief Fetch the current global event loop.
*
* @return EventLoop& The current global event loop.
*/
static EventLoop& the();
/**
* @brief Register a new event listener on a file descriptor.
*
* @param fd The file descriptor to listen on.
* @param listener The callback function to invoke when events occur on the file descriptor. The first parameter
* is the file descriptor registered, and the second argument is the type of event (POLLIN or POLLHUP)
* @return Result<void> Whether the operation succeeded.
*/
Result<void> register_fd_listener(int fd, void (*listener)(int, int));
/**
* @brief Register a new POSIX signal handler.
*
* Unlike standard POSIX signal handling, this handler will be run synchronously as part of the event loop,
* eliminating many problems with asynchronous signal handling.
*
* @param sig The signal to handle.
* @param handler The function to call when this signal is caught.
* @return Result<void> Whether the operation succeeded.
*/
Result<void> register_signal_handler(int sig, void (*handler)(int));
/**
* @brief Run the event loop until it is asked to quit.
*
* @return int The status passed to the quit() method.
*/
int run();
/**
* @brief Ask the event loop to quit.
*
* @param status The status value to return from run().
*/
void quit(int status = 0);
private:
HashMap<int, void (*)(int, int)> m_fd_listeners;
HashMap<int, void (*)(int)> m_signal_handlers;
Vector<struct pollfd> m_pollfds;
static void handle_signal(int sig);
static void handle_quit_signal(int);
static void handle_timer_signal(int);
bool m_should_quit { false };
int m_quit_status { 0 };
int m_signal_pipe[2];
LinkedList<Timer> m_timer_list;
friend class Timer;
};
}