Skip to content

Commit 8ab3402

Browse files
committed
add doOnReadable to event loop manager
1 parent 3002845 commit 8ab3402

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

src/managers/eventLoop/EventLoopManager.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ CEventLoopManager::~CEventLoopManager() {
2626
wl_event_source_remove(eventSourceData.eventSource);
2727
}
2828

29+
for (auto const& w : m_vReadableWaiters) {
30+
if (w->source != nullptr)
31+
wl_event_source_remove(w->source);
32+
}
33+
2934
if (m_sWayland.eventSource)
3035
wl_event_source_remove(m_sWayland.eventSource);
3136
if (m_sIdle.eventSource)
@@ -50,6 +55,33 @@ static int configWatcherWrite(int fd, uint32_t mask, void* data) {
5055
return 0;
5156
}
5257

58+
static int handleWaiterFD(int fd, uint32_t mask, void* data) {
59+
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
60+
Debug::log(ERR, "handleWaiterFD: readable waiter error");
61+
return 0;
62+
}
63+
64+
if (mask & WL_EVENT_READABLE)
65+
g_pEventLoopManager->onFdReadable((CEventLoopManager::SReadableWaiter*)data);
66+
67+
return 0;
68+
}
69+
70+
void CEventLoopManager::onFdReadable(SReadableWaiter* waiter) {
71+
auto it = std::ranges::find_if(m_vReadableWaiters, [waiter](const UP<SReadableWaiter>& w) { return waiter == w.get() && w->fd == waiter->fd && w->source == waiter->source; });
72+
73+
if (waiter->source) {
74+
wl_event_source_remove(waiter->source);
75+
waiter->source = nullptr;
76+
}
77+
78+
if (waiter->fn)
79+
waiter->fn();
80+
81+
if (it != m_vReadableWaiters.end())
82+
m_vReadableWaiters.erase(it);
83+
}
84+
5385
void CEventLoopManager::enterLoop() {
5486
m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd.get(), WL_EVENT_READABLE, timerWrite, nullptr);
5587

@@ -143,6 +175,16 @@ void CEventLoopManager::doLater(const std::function<void()>& fn) {
143175
&m_sIdle);
144176
}
145177

178+
void CEventLoopManager::doOnReadable(CFileDescriptor fd, const std::function<void()>& fn) {
179+
if (!fd.isValid() || fd.isReadable()) {
180+
fn();
181+
return;
182+
}
183+
184+
auto& waiter = m_vReadableWaiters.emplace_back(makeUnique<SReadableWaiter>(nullptr, std::move(fd), fn));
185+
waiter->source = wl_event_loop_add_fd(g_pEventLoopManager->m_sWayland.loop, waiter->fd.get(), WL_EVENT_READABLE, ::handleWaiterFD, waiter.get());
186+
}
187+
146188
void CEventLoopManager::syncPollFDs() {
147189
auto aqPollFDs = g_pCompositor->m_pAqBackend->getPollFDs();
148190

src/managers/eventLoop/EventLoopManager.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ class CEventLoopManager {
3838
std::vector<std::function<void()>> fns;
3939
};
4040

41+
struct SReadableWaiter {
42+
wl_event_source* source;
43+
Hyprutils::OS::CFileDescriptor fd;
44+
std::function<void()> fn;
45+
};
46+
47+
// schedule function to when fd is readable (WL_EVENT_READABLE / POLLIN),
48+
// takes ownership of fd
49+
void doOnReadable(Hyprutils::OS::CFileDescriptor fd, const std::function<void()>& fn);
50+
void onFdReadable(SReadableWaiter* waiter);
51+
4152
private:
4253
// Manages the event sources after AQ pollFDs change.
4354
void syncPollFDs();
@@ -58,8 +69,9 @@ class CEventLoopManager {
5869
Hyprutils::OS::CFileDescriptor timerfd;
5970
} m_sTimers;
6071

61-
SIdleData m_sIdle;
62-
std::map<int, SEventSourceData> aqEventSources;
72+
SIdleData m_sIdle;
73+
std::map<int, SEventSourceData> aqEventSources;
74+
std::vector<UP<SReadableWaiter>> m_vReadableWaiters;
6375

6476
struct {
6577
CHyprSignalListener pollFDsChanged;

0 commit comments

Comments
 (0)