diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-07-14 10:20:57 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-07-14 10:20:57 +0200 |
commit | 17ee548bcd8d9111addcc291457ad316e620d5e6 (patch) | |
tree | 37d6dda4eebe35ee78d15a1b0958f76e67e6e2b5 /Libraries/LibCore/CEventLoop.cpp | |
parent | f1d6a37d5dca1593e78e39a33714730dc0348224 (diff) | |
download | serenity-17ee548bcd8d9111addcc291457ad316e620d5e6.zip |
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.
Diffstat (limited to 'Libraries/LibCore/CEventLoop.cpp')
-rw-r--r-- | Libraries/LibCore/CEventLoop.cpp | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/Libraries/LibCore/CEventLoop.cpp b/Libraries/LibCore/CEventLoop.cpp index 090f2a20af..88e719d9dd 100644 --- a/Libraries/LibCore/CEventLoop.cpp +++ b/Libraries/LibCore/CEventLoop.cpp @@ -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(¬ifier); } + +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(); + } +} |