mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:17:44 +00:00
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.
This commit is contained in:
parent
716a3429fa
commit
704bb361bb
4 changed files with 27 additions and 9 deletions
|
@ -849,7 +849,7 @@ void HackStudioWidget::initialize_debugger()
|
||||||
m_disassembly_widget->update_state(*Debugger::the().session(), regs);
|
m_disassembly_widget->update_state(*Debugger::the().session(), regs);
|
||||||
HackStudioWidget::reveal_action_tab(*m_debug_info_widget);
|
HackStudioWidget::reveal_action_tab(*m_debug_info_widget);
|
||||||
});
|
});
|
||||||
Core::EventLoop::wake();
|
Core::EventLoop::wake_current();
|
||||||
|
|
||||||
return Debugger::HasControlPassedToUser::Yes;
|
return Debugger::HasControlPassedToUser::Yes;
|
||||||
},
|
},
|
||||||
|
@ -859,7 +859,7 @@ void HackStudioWidget::initialize_debugger()
|
||||||
if (m_current_editor_in_execution)
|
if (m_current_editor_in_execution)
|
||||||
m_current_editor_in_execution->editor().clear_execution_position();
|
m_current_editor_in_execution->editor().clear_execution_position();
|
||||||
});
|
});
|
||||||
Core::EventLoop::wake();
|
Core::EventLoop::wake_current();
|
||||||
},
|
},
|
||||||
[this]() {
|
[this]() {
|
||||||
deferred_invoke([this] {
|
deferred_invoke([this] {
|
||||||
|
@ -879,7 +879,7 @@ void HackStudioWidget::initialize_debugger()
|
||||||
HackStudioWidget::hide_action_tabs();
|
HackStudioWidget::hide_action_tabs();
|
||||||
GUI::MessageBox::show(window(), "Program Exited", "Debugger", GUI::MessageBox::Type::Information);
|
GUI::MessageBox::show(window(), "Program Exited", "Debugger", GUI::MessageBox::Type::Information);
|
||||||
});
|
});
|
||||||
Core::EventLoop::wake();
|
Core::EventLoop::wake_current();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
EventLoop::EventLoop([[maybe_unused]] MakeInspectable make_inspectable)
|
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__
|
#ifdef __serenity__
|
||||||
if (!s_global_initializers_ran) {
|
if (!s_global_initializers_ran) {
|
||||||
|
@ -487,11 +488,13 @@ size_t EventLoop::pump(WaitMode mode)
|
||||||
return processed_events;
|
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);
|
Threading::MutexLocker lock(m_private->lock);
|
||||||
dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::post_event: ({}) << receiver={}, event={}", m_queued_events.size(), receiver, event);
|
dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::post_event: ({}) << receiver={}, event={}", m_queued_events.size(), receiver, event);
|
||||||
m_queued_events.empend(receiver, move(event));
|
m_queued_events.empend(receiver, move(event));
|
||||||
|
if (should_wake == ShouldWake::Yes)
|
||||||
|
wake();
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalHandlers::SignalHandlers(int signo, void (*handle_signal)(int))
|
SignalHandlers::SignalHandlers(int signo, void (*handle_signal)(int))
|
||||||
|
@ -839,10 +842,16 @@ void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier)
|
||||||
s_notifiers->remove(¬ifier);
|
s_notifiers->remove(¬ifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EventLoop::wake_current()
|
||||||
|
{
|
||||||
|
EventLoop::current().wake();
|
||||||
|
}
|
||||||
|
|
||||||
void EventLoop::wake()
|
void EventLoop::wake()
|
||||||
{
|
{
|
||||||
|
dbgln_if(EVENTLOOP_DEBUG, "Core::EventLoop::wake()");
|
||||||
int wake_event = 0;
|
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) {
|
if (nwritten < 0) {
|
||||||
perror("EventLoop::wake: write");
|
perror("EventLoop::wake: write");
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
|
|
@ -34,6 +34,11 @@ public:
|
||||||
Yes,
|
Yes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ShouldWake {
|
||||||
|
No,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
|
||||||
explicit EventLoop(MakeInspectable = MakeInspectable::No);
|
explicit EventLoop(MakeInspectable = MakeInspectable::No);
|
||||||
~EventLoop();
|
~EventLoop();
|
||||||
static void initialize_wake_pipes();
|
static void initialize_wake_pipes();
|
||||||
|
@ -51,7 +56,7 @@ public:
|
||||||
|
|
||||||
void spin_until(Function<bool()>);
|
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>
|
template<typename Callback>
|
||||||
static decltype(auto) with_main_locked(Callback callback)
|
static decltype(auto) with_main_locked(Callback callback)
|
||||||
|
@ -79,7 +84,8 @@ public:
|
||||||
m_queued_events.extend(move(other.m_queued_events));
|
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 int register_signal(int signo, Function<void(int)> handler);
|
||||||
static void unregister_signal(int handler_id);
|
static void unregister_signal(int handler_id);
|
||||||
|
@ -126,6 +132,9 @@ private:
|
||||||
static thread_local int s_wake_pipe_fds[2];
|
static thread_local int s_wake_pipe_fds[2];
|
||||||
static thread_local bool s_wake_pipe_initialized;
|
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;
|
struct Private;
|
||||||
NonnullOwnPtr<Private> m_private;
|
NonnullOwnPtr<Private> m_private;
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,7 +63,7 @@ private:
|
||||||
m_on_complete(m_result.release_value());
|
m_on_complete(m_result.release_value());
|
||||||
remove_from_parent();
|
remove_from_parent();
|
||||||
});
|
});
|
||||||
Core::EventLoop::wake();
|
origin_event_loop->wake();
|
||||||
} else {
|
} else {
|
||||||
this->remove_from_parent();
|
this->remove_from_parent();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue