1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-30 15:38:12 +00:00

CEventLoop: Add wake(), a mechanism for waking up when blocked in select().

This patch generalizes the concept used in Piano to wake up the event loop
so it can react to something happening on a secondary thread.
Basically, there's a pipe who is always part of the file descriptor set we
pass to select(), and calling wake() simply writes a little to that pipe.
This commit is contained in:
Andreas Kling 2019-07-14 10:20:57 +02:00
parent f1d6a37d5d
commit 17ee548bcd
2 changed files with 23 additions and 0 deletions

View file

@ -23,6 +23,7 @@ static Vector<CEventLoop*>* s_event_loop_stack;
HashMap<int, OwnPtr<CEventLoop::EventLoopTimer>>* CEventLoop::s_timers;
HashTable<CNotifier*>* CEventLoop::s_notifiers;
int CEventLoop::s_next_timer_id = 1;
int CEventLoop::s_wake_pipe_fds[2];
CEventLoop::CEventLoop()
{
@ -34,6 +35,8 @@ CEventLoop::CEventLoop()
if (!s_main_event_loop) {
s_main_event_loop = this;
int rc = pipe(s_wake_pipe_fds);
ASSERT(rc == 0);
s_event_loop_stack->append(this);
}
@ -169,6 +172,7 @@ void CEventLoop::wait_for_event(WaitMode mode)
int max_fd_added = -1;
add_file_descriptors_for_select(rfds, max_fd_added);
add_fd_to_set(s_wake_pipe_fds[1], rfds);
max_fd = max(max_fd, max_fd_added);
for (auto& notifier : *s_notifiers) {
if (notifier->event_mask() & CNotifier::Read)
@ -205,6 +209,11 @@ void CEventLoop::wait_for_event(WaitMode mode)
ASSERT_NOT_REACHED();
}
if (FD_ISSET(s_wake_pipe_fds[1], &rfds)) {
char buffer[32];
read(s_wake_pipe_fds[1], buffer, sizeof(buffer));
}
if (!s_timers->is_empty()) {
gettimeofday(&now, nullptr);
}
@ -301,3 +310,13 @@ void CEventLoop::unregister_notifier(Badge<CNotifier>, CNotifier& notifier)
{
s_notifiers->remove(&notifier);
}
void CEventLoop::wake()
{
char ch = '!';
int nwritten = write(s_wake_pipe_fds[0], &ch, 1);
if (nwritten < 0) {
perror("CEventLoop::wake: write");
ASSERT_NOT_REACHED();
}
}