mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-05 01:10:24 +00:00
LibCore: Allow posting stateless events without heap-allocated Event
This patch adds an API for posting a Core::Event::Type to the thread event queue without requiring a full Core::Event object. We use this API to avoid heap allocations for every timer and notifier activation event.
This commit is contained in:
committed by
Andreas Kling
parent
23fb9781d1
commit
69515f8c85
Notes:
github-actions[bot]
2025-12-03 12:27:51 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/69515f8c854 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/7004
@@ -210,7 +210,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
ThreadEventQueue::current().post_event(strong_owner, make<TimerEvent>());
|
||||
ThreadEventQueue::current().post_event(strong_owner, Event::Type::Timer);
|
||||
}
|
||||
|
||||
AK::Duration interval;
|
||||
@@ -405,7 +405,7 @@ try_select_again:
|
||||
|
||||
#ifdef AK_OS_ANDROID
|
||||
// FIXME: Make the check work under Android, perhaps use ALooper.
|
||||
ThreadEventQueue::current().post_event(notifier, make<NotifierActivationEvent>());
|
||||
ThreadEventQueue::current().post_event(notifier, Core::Event::Type::NotifierActivation);
|
||||
#else
|
||||
auto revents = thread_data.poll_fds[i].revents;
|
||||
|
||||
@@ -422,7 +422,7 @@ try_select_again:
|
||||
type &= notifier.type();
|
||||
|
||||
if (type != NotificationType::None)
|
||||
ThreadEventQueue::current().post_event(¬ifier, make<NotifierActivationEvent>());
|
||||
ThreadEventQueue::current().post_event(¬ifier, Core::Event::Type::NotifierActivation);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ size_t EventLoopImplementationWindows::pump(PumpMode pump_mode)
|
||||
if (packet->type == CompletionType::Timer) {
|
||||
auto* timer = static_cast<EventLoopTimer*>(packet);
|
||||
if (auto owner = timer->owner.strong_ref())
|
||||
event_queue.post_event(owner, make<TimerEvent>());
|
||||
event_queue.post_event(owner, Event::Type::Timer);
|
||||
if (timer->is_periodic) {
|
||||
NTSTATUS status = g_system.NtAssociateWaitCompletionPacket(timer->wait_packet.handle, thread_data->iocp.handle, timer->timer.handle, timer, NULL, 0, 0, NULL);
|
||||
VERIFY(NT_SUCCESS(status));
|
||||
@@ -205,7 +205,7 @@ size_t EventLoopImplementationWindows::pump(PumpMode pump_mode)
|
||||
}
|
||||
if (packet->type == CompletionType::Notifer) {
|
||||
auto* notifier_data = static_cast<EventLoopNotifier*>(packet);
|
||||
event_queue.post_event(notifier_data->notifier, make<NotifierActivationEvent>());
|
||||
event_queue.post_event(notifier_data->notifier, Core::Event::Type::NotifierActivation);
|
||||
NTSTATUS status = g_system.NtAssociateWaitCompletionPacket(notifier_data->wait_packet.handle, thread_data->iocp.handle, notifier_data->wait_event.handle, notifier_data, NULL, 0, 0, NULL);
|
||||
VERIFY(NT_SUCCESS(status));
|
||||
continue;
|
||||
|
||||
@@ -24,13 +24,21 @@ struct ThreadEventQueue::Private {
|
||||
QueuedEvent(RefPtr<EventReceiver> const& receiver, NonnullOwnPtr<Event> event)
|
||||
: receiver(receiver)
|
||||
, event(move(event))
|
||||
, event_type(this->event->type())
|
||||
{
|
||||
}
|
||||
|
||||
QueuedEvent(RefPtr<EventReceiver> const& receiver, Event::Type event_type)
|
||||
: receiver(receiver)
|
||||
, event_type(event_type)
|
||||
{
|
||||
}
|
||||
|
||||
~QueuedEvent() = default;
|
||||
|
||||
WeakPtr<EventReceiver> receiver;
|
||||
NonnullOwnPtr<Event> event;
|
||||
OwnPtr<Event> event;
|
||||
u8 event_type { Event::Type::Invalid };
|
||||
};
|
||||
|
||||
Threading::Mutex mutex;
|
||||
@@ -75,6 +83,15 @@ void ThreadEventQueue::post_event(Core::EventReceiver* receiver, NonnullOwnPtr<C
|
||||
Core::EventLoopManager::the().did_post_event();
|
||||
}
|
||||
|
||||
void ThreadEventQueue::post_event(Core::EventReceiver* receiver, Core::Event::Type event_type)
|
||||
{
|
||||
{
|
||||
Threading::MutexLocker lock(m_private->mutex);
|
||||
m_private->queued_events.empend(receiver, event_type);
|
||||
}
|
||||
Core::EventLoopManager::the().did_post_event();
|
||||
}
|
||||
|
||||
void ThreadEventQueue::add_job(NonnullRefPtr<Promise<NonnullRefPtr<EventReceiver>>> promise)
|
||||
{
|
||||
Threading::MutexLocker lock(m_private->mutex);
|
||||
@@ -100,14 +117,29 @@ size_t ThreadEventQueue::process()
|
||||
}
|
||||
|
||||
size_t processed_events = 0;
|
||||
for (size_t i = 0; i < events.size(); ++i) {
|
||||
auto& queued_event = events.at(i);
|
||||
auto& event = *queued_event.event;
|
||||
|
||||
if (event.type() == Event::Type::DeferredInvoke) {
|
||||
static_cast<DeferredInvocationEvent&>(event).m_invokee();
|
||||
} else if (auto receiver = queued_event.receiver.strong_ref()) {
|
||||
receiver->dispatch_event(event);
|
||||
for (auto& queued_event : events) {
|
||||
if (auto receiver = queued_event.receiver.strong_ref()) {
|
||||
switch (queued_event.event_type) {
|
||||
case Event::Type::Timer: {
|
||||
TimerEvent timer_event;
|
||||
receiver->dispatch_event(timer_event);
|
||||
break;
|
||||
}
|
||||
case Event::Type::NotifierActivation: {
|
||||
NotifierActivationEvent notifier_activation_event;
|
||||
receiver->dispatch_event(notifier_activation_event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
receiver->dispatch_event(*queued_event.event);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (queued_event.event_type == Event::Type::DeferredInvoke) {
|
||||
static_cast<DeferredInvocationEvent&>(*queued_event.event).m_invokee();
|
||||
} else {
|
||||
// Receiver gone, drop the event.
|
||||
}
|
||||
}
|
||||
++processed_events;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
// Posts an event to the event queue.
|
||||
void post_event(EventReceiver*, NonnullOwnPtr<Event>);
|
||||
void post_event(EventReceiver*, Core::Event::Type);
|
||||
|
||||
// Used by Threading::BackgroundAction.
|
||||
void add_job(NonnullRefPtr<Promise<NonnullRefPtr<EventReceiver>>>);
|
||||
|
||||
@@ -25,7 +25,7 @@ Java_org_serenityos_ladybird_TimerExecutorService_00024Timer_nativeRun(JNIEnv*,
|
||||
if (!receiver)
|
||||
return;
|
||||
|
||||
event_loop_impl.post_event(*receiver, make<Core::TimerEvent>());
|
||||
event_loop_impl.post_event(*receiver, Core::Event::Type::Timer);
|
||||
}
|
||||
// Flush the event loop on this thread to keep any garbage from building up
|
||||
if (auto num_events = s_event_loop.pump(Core::EventLoop::WaitMode::PollForEvents); num_events != 0) {
|
||||
|
||||
Reference in New Issue
Block a user