2024-04-07 04:31:51 +02:00
|
|
|
#include "EventLoopManager.hpp"
|
|
|
|
#include "../../debug/Log.hpp"
|
|
|
|
|
|
|
|
#include <algorithm>
|
2024-04-07 22:55:14 +02:00
|
|
|
#include <limits>
|
2024-04-07 04:31:51 +02:00
|
|
|
|
|
|
|
#include <sys/poll.h>
|
2024-04-07 22:55:14 +02:00
|
|
|
#include <sys/timerfd.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#define TIMESPEC_NSEC_PER_SEC 1000000000L
|
|
|
|
|
|
|
|
CEventLoopManager::CEventLoopManager() {
|
|
|
|
m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int timerWrite(int fd, uint32_t mask, void* data) {
|
|
|
|
g_pEventLoopManager->onTimerFire();
|
|
|
|
return 1;
|
|
|
|
}
|
2024-04-07 04:31:51 +02:00
|
|
|
|
|
|
|
void CEventLoopManager::enterLoop(wl_display* display, wl_event_loop* wlEventLoop) {
|
|
|
|
m_sWayland.loop = wlEventLoop;
|
|
|
|
m_sWayland.display = display;
|
|
|
|
|
2024-04-07 22:55:14 +02:00
|
|
|
wl_event_loop_add_fd(wlEventLoop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr);
|
|
|
|
|
|
|
|
wl_display_run(display);
|
2024-04-07 04:31:51 +02:00
|
|
|
|
|
|
|
Debug::log(LOG, "Kicked off the event loop! :(");
|
2024-04-07 22:55:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CEventLoopManager::onTimerFire() {
|
|
|
|
for (auto& t : m_sTimers.timers) {
|
|
|
|
if (t->passed() && !t->cancelled())
|
|
|
|
t->call(t);
|
|
|
|
}
|
2024-04-07 04:31:51 +02:00
|
|
|
|
2024-04-07 22:55:14 +02:00
|
|
|
nudgeTimers();
|
2024-04-07 04:31:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CEventLoopManager::addTimer(std::shared_ptr<CEventLoopTimer> timer) {
|
|
|
|
m_sTimers.timers.push_back(timer);
|
|
|
|
nudgeTimers();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CEventLoopManager::removeTimer(std::shared_ptr<CEventLoopTimer> timer) {
|
|
|
|
std::erase_if(m_sTimers.timers, [timer](const auto& t) { return timer == t; });
|
2024-04-07 22:55:14 +02:00
|
|
|
nudgeTimers();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void timespecAddNs(timespec* pTimespec, int64_t delta) {
|
|
|
|
int delta_ns_low = delta % TIMESPEC_NSEC_PER_SEC;
|
|
|
|
int delta_s_high = delta / TIMESPEC_NSEC_PER_SEC;
|
|
|
|
|
|
|
|
pTimespec->tv_sec += delta_s_high;
|
|
|
|
|
|
|
|
pTimespec->tv_nsec += (long)delta_ns_low;
|
|
|
|
if (pTimespec->tv_nsec >= TIMESPEC_NSEC_PER_SEC) {
|
|
|
|
pTimespec->tv_nsec -= TIMESPEC_NSEC_PER_SEC;
|
|
|
|
++pTimespec->tv_sec;
|
|
|
|
}
|
2024-04-07 04:31:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CEventLoopManager::nudgeTimers() {
|
2024-04-07 22:55:14 +02:00
|
|
|
|
|
|
|
long nextTimerUs = 10 * 1000 * 1000; // 10s
|
|
|
|
|
|
|
|
for (auto& t : m_sTimers.timers) {
|
|
|
|
if (const auto µs = t->leftUs(); µs < nextTimerUs)
|
|
|
|
nextTimerUs = µs;
|
|
|
|
}
|
|
|
|
|
|
|
|
nextTimerUs = std::clamp(nextTimerUs + 1, 1L, std::numeric_limits<long>::max());
|
|
|
|
|
|
|
|
timespec now;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
|
timespecAddNs(&now, nextTimerUs * 1000L);
|
|
|
|
|
|
|
|
itimerspec ts = {.it_value = now};
|
|
|
|
|
|
|
|
timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr);
|
2024-04-07 04:31:51 +02:00
|
|
|
}
|