diff options
author | kleines Filmröllchen <filmroellchen@serenityos.org> | 2022-02-11 16:57:10 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-13 23:06:53 +0100 |
commit | 704bb361bbb40f01259d963ae5d20cd4b9c51482 (patch) | |
tree | d2deea719854c76d6933571cca392332d1e8bb72 /Userland | |
parent | 716a3429fa2693bc512b19d25e524c34b58049c5 (diff) | |
download | serenity-704bb361bbb40f01259d963ae5d20cd4b9c51482.zip |
LibCore: Allow event loops on other threads to wake up
Because the wake pipe is thread-local, it was previously not possible
to wake an event loop across a thread. Therefore, this commit
rearchitects event loop waking by making the wake function a member of
the event loop itself and having it keep a pointer to its thread's wake
pipe. The global wake() function calls wake on the current thread's
event loop.
This also fixes a bug in BackgroundAction: it should wake the event loop
it was created on, instead of the current thread's event loop.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/DevTools/HackStudio/HackStudioWidget.cpp | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/EventLoop.cpp | 15 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/EventLoop.h | 13 | ||||
-rw-r--r-- | Userland/Libraries/LibThreading/BackgroundAction.h | 2 |
4 files changed, 27 insertions, 9 deletions
diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.cpp b/Userland/DevTools/HackStudio/HackStudioWidget.cpp index 336010d987..73009fc783 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.cpp +++ b/Userland/DevTools/HackStudio/HackStudioWidget.cpp @@ -849,7 +849,7 @@ void HackStudioWidget::initialize_debugger() m_disassembly_widget->update_state(*Debugger::the().session(), regs); HackStudioWidget::reveal_action_tab(*m_debug_info_widget); }); - Core::EventLoop::wake(); + Core::EventLoop::wake_current(); return Debugger::HasControlPassedToUser::Yes; }, @@ -859,7 +859,7 @@ void HackStudioWidget::initialize_debugger() if (m_current_editor_in_execution) m_current_editor_in_execution->editor().clear_execution_position(); }); - Core::EventLoop::wake(); + Core::EventLoop::wake_current(); }, [this]() { deferred_invoke([this] { @@ -879,7 +879,7 @@ void HackStudioWidget::initialize_debugger() HackStudioWidget::hide_action_tabs(); GUI::MessageBox::show(window(), "Program Exited", "Debugger", GUI::MessageBox::Type::Information); }); - Core::EventLoop::wake(); + Core::EventLoop::wake_current(); }); } diff --git a/Userland/Libraries/LibCore/EventLoop.cpp b/Userland/Libraries/LibCore/EventLoop.cpp index 2c2a9f6fe1..42734be04d 100644 --- a/Userland/Libraries/LibCore/EventLoop.cpp +++ b/Userland/Libraries/LibCore/EventLoop.cpp @@ -302,7 +302,8 @@ private: }; EventLoop::EventLoop([[maybe_unused]] MakeInspectable make_inspectable) - : m_private(make<Private>()) + : m_wake_pipe_fds(&s_wake_pipe_fds) + , m_private(make<Private>()) { #ifdef __serenity__ if (!s_global_initializers_ran) { @@ -487,11 +488,13 @@ size_t EventLoop::pump(WaitMode mode) return processed_events; } -void EventLoop::post_event(Object& receiver, NonnullOwnPtr<Event>&& event) +void EventLoop::post_event(Object& receiver, NonnullOwnPtr<Event>&& event, ShouldWake should_wake) { Threading::MutexLocker lock(m_private->lock); dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::post_event: ({}) << receiver={}, event={}", m_queued_events.size(), receiver, event); m_queued_events.empend(receiver, move(event)); + if (should_wake == ShouldWake::Yes) + wake(); } SignalHandlers::SignalHandlers(int signo, void (*handle_signal)(int)) @@ -839,10 +842,16 @@ void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier) s_notifiers->remove(¬ifier); } +void EventLoop::wake_current() +{ + EventLoop::current().wake(); +} + void EventLoop::wake() { + dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::wake()"); int wake_event = 0; - int nwritten = write(s_wake_pipe_fds[1], &wake_event, sizeof(wake_event)); + int nwritten = write((*m_wake_pipe_fds)[1], &wake_event, sizeof(wake_event)); if (nwritten < 0) { perror("EventLoop::wake: write"); VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibCore/EventLoop.h b/Userland/Libraries/LibCore/EventLoop.h index dbdaa146c1..294be5bbec 100644 --- a/Userland/Libraries/LibCore/EventLoop.h +++ b/Userland/Libraries/LibCore/EventLoop.h @@ -34,6 +34,11 @@ public: Yes, }; + enum class ShouldWake { + No, + Yes + }; + explicit EventLoop(MakeInspectable = MakeInspectable::No); ~EventLoop(); static void initialize_wake_pipes(); @@ -51,7 +56,7 @@ public: void spin_until(Function<bool()>); - void post_event(Object& receiver, NonnullOwnPtr<Event>&&); + void post_event(Object& receiver, NonnullOwnPtr<Event>&&, ShouldWake = ShouldWake::No); template<typename Callback> static decltype(auto) with_main_locked(Callback callback) @@ -79,7 +84,8 @@ public: m_queued_events.extend(move(other.m_queued_events)); } - static void wake(); + static void wake_current(); + void wake(); static int register_signal(int signo, Function<void(int)> handler); static void unregister_signal(int handler_id); @@ -126,6 +132,9 @@ private: static thread_local int s_wake_pipe_fds[2]; static thread_local bool s_wake_pipe_initialized; + // The wake pipe of this event loop needs to be accessible from other threads. + int (*m_wake_pipe_fds)[2]; + struct Private; NonnullOwnPtr<Private> m_private; }; diff --git a/Userland/Libraries/LibThreading/BackgroundAction.h b/Userland/Libraries/LibThreading/BackgroundAction.h index 39d2bf5f4b..ee2b95dd80 100644 --- a/Userland/Libraries/LibThreading/BackgroundAction.h +++ b/Userland/Libraries/LibThreading/BackgroundAction.h @@ -63,7 +63,7 @@ private: m_on_complete(m_result.release_value()); remove_from_parent(); }); - Core::EventLoop::wake(); + origin_event_loop->wake(); } else { this->remove_from_parent(); } |