2023-10-06 20:06:34 +00:00
|
|
|
/**
|
|
|
|
* @file EventLoop.h
|
|
|
|
* @author apio (cloudapio.eu)
|
|
|
|
* @brief Base class for event-driven applications.
|
|
|
|
*
|
2024-01-05 21:16:50 +00:00
|
|
|
* @copyright Copyright (c) 2023-2024, the Luna authors.
|
2023-10-06 20:06:34 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
2024-10-19 19:25:17 +00:00
|
|
|
#include <luna/Action.h>
|
2023-10-06 20:06:34 +00:00
|
|
|
#include <luna/HashMap.h>
|
|
|
|
#include <luna/Vector.h>
|
2024-01-05 21:16:50 +00:00
|
|
|
#include <os/Timer.h>
|
2023-10-06 20:06:34 +00:00
|
|
|
#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.
|
|
|
|
*/
|
2024-01-18 19:52:36 +00:00
|
|
|
Result<void> register_fd_listener(int fd, Function<int, int> listener);
|
2023-10-06 20:06:34 +00:00
|
|
|
|
2023-10-07 12:26:35 +00:00
|
|
|
/**
|
|
|
|
* @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.
|
2023-10-09 20:00:15 +00:00
|
|
|
*
|
|
|
|
* @param sig The signal to handle.
|
|
|
|
* @param handler The function to call when this signal is caught.
|
|
|
|
* @return Result<void> Whether the operation succeeded.
|
2023-10-07 12:26:35 +00:00
|
|
|
*/
|
2024-01-18 19:52:36 +00:00
|
|
|
Result<void> register_signal_handler(int sig, Function<int> handler);
|
2023-10-07 12:26:35 +00:00
|
|
|
|
2023-10-06 20:06:34 +00:00
|
|
|
/**
|
|
|
|
* @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:
|
2024-01-18 19:52:36 +00:00
|
|
|
HashMap<int, Function<int, int>> m_fd_listeners;
|
|
|
|
HashMap<int, Function<int>> m_signal_handlers;
|
2023-10-06 20:06:34 +00:00
|
|
|
Vector<struct pollfd> m_pollfds;
|
|
|
|
|
2023-10-07 12:26:35 +00:00
|
|
|
static void handle_signal(int sig);
|
|
|
|
static void handle_quit_signal(int);
|
2023-10-09 20:00:15 +00:00
|
|
|
static void handle_timer_signal(int);
|
2023-10-07 12:26:35 +00:00
|
|
|
|
2023-10-06 20:06:34 +00:00
|
|
|
bool m_should_quit { false };
|
|
|
|
int m_quit_status { 0 };
|
2023-10-07 12:26:35 +00:00
|
|
|
|
|
|
|
int m_signal_pipe[2];
|
2023-10-09 20:00:15 +00:00
|
|
|
|
2024-01-05 21:16:50 +00:00
|
|
|
LinkedList<Timer> m_timer_list;
|
2023-10-09 20:00:15 +00:00
|
|
|
|
2024-01-05 21:16:50 +00:00
|
|
|
friend class Timer;
|
2023-10-06 20:06:34 +00:00
|
|
|
};
|
|
|
|
}
|