mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-05-11 17:37:33 +02:00
This commit splits out synchronization primitives from LibThreading into LibSync. This is because LibThreading depends on LibCore, while LibCore needs the synchronization primitives from LibThreading. This worked while they were header only, but when I tried to add an implementation file it ran into the circular dependency. To abstract away the pthread implementation using cpp files is necessary so the synchronization primitives were moved to a separate library.
219 lines
5.0 KiB
C++
219 lines
5.0 KiB
C++
/*
|
|
* Copyright (c) 2018-2023, Andreas Kling <andreas@ladybird.org>
|
|
* Copyright (c) 2022, kleines Filmröllchen <malu.bertsch@gmail.com>
|
|
* Copyright (c) 2022, the SerenityOS developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/Badge.h>
|
|
#include <AK/Vector.h>
|
|
#include <LibCore/EventLoop.h>
|
|
#include <LibCore/EventLoopImplementation.h>
|
|
#include <LibCore/EventReceiver.h>
|
|
#include <LibCore/Promise.h>
|
|
#include <LibCore/ThreadEventQueue.h>
|
|
|
|
namespace Core {
|
|
|
|
namespace {
|
|
|
|
OwnPtr<Vector<EventLoop&>>& event_loop_stack_uninitialized()
|
|
{
|
|
thread_local OwnPtr<Vector<EventLoop&>> s_event_loop_stack = nullptr;
|
|
return s_event_loop_stack;
|
|
}
|
|
Vector<EventLoop&>& event_loop_stack()
|
|
{
|
|
auto& the_stack = event_loop_stack_uninitialized();
|
|
if (the_stack == nullptr)
|
|
the_stack = make<Vector<EventLoop&>>();
|
|
return *the_stack;
|
|
}
|
|
|
|
}
|
|
|
|
EventLoop::EventLoop()
|
|
: m_impl(EventLoopManager::the().make_implementation())
|
|
{
|
|
if (event_loop_stack().is_empty()) {
|
|
event_loop_stack().append(*this);
|
|
}
|
|
}
|
|
|
|
EventLoop::~EventLoop()
|
|
{
|
|
if (m_weak)
|
|
m_weak->revoke();
|
|
if (!event_loop_stack().is_empty() && &event_loop_stack().last() == this) {
|
|
event_loop_stack().take_last();
|
|
}
|
|
}
|
|
|
|
bool EventLoop::is_running()
|
|
{
|
|
auto& stack = event_loop_stack_uninitialized();
|
|
return stack != nullptr && !stack->is_empty();
|
|
}
|
|
|
|
EventLoop& EventLoop::current()
|
|
{
|
|
if (event_loop_stack().is_empty())
|
|
dbgln("No EventLoop is present, unable to return current one!");
|
|
return event_loop_stack().last();
|
|
}
|
|
|
|
NonnullRefPtr<WeakEventLoopReference> EventLoop::current_weak()
|
|
{
|
|
auto& event_loop = current();
|
|
if (!event_loop.m_weak)
|
|
event_loop.m_weak = adopt_ref(*new (nothrow) WeakEventLoopReference(event_loop));
|
|
return *event_loop.m_weak;
|
|
}
|
|
|
|
void EventLoop::quit(int code)
|
|
{
|
|
m_impl->quit(code);
|
|
}
|
|
|
|
bool EventLoop::was_exit_requested()
|
|
{
|
|
return m_impl->was_exit_requested();
|
|
}
|
|
|
|
struct EventLoopPusher {
|
|
public:
|
|
EventLoopPusher(EventLoop& event_loop)
|
|
{
|
|
event_loop_stack().append(event_loop);
|
|
}
|
|
~EventLoopPusher()
|
|
{
|
|
event_loop_stack().take_last();
|
|
}
|
|
};
|
|
|
|
int EventLoop::exec()
|
|
{
|
|
EventLoopPusher pusher(*this);
|
|
return m_impl->exec();
|
|
}
|
|
|
|
void EventLoop::spin_until(Function<bool()> goal_condition)
|
|
{
|
|
EventLoopPusher pusher(*this);
|
|
while (!goal_condition())
|
|
pump();
|
|
}
|
|
|
|
size_t EventLoop::pump(WaitMode mode)
|
|
{
|
|
return m_impl->pump(mode == WaitMode::WaitForEvents ? EventLoopImplementation::PumpMode::WaitForEvents : EventLoopImplementation::PumpMode::DontWaitForEvents);
|
|
}
|
|
|
|
int EventLoop::register_signal(int signal_number, Function<void(int)> handler)
|
|
{
|
|
return EventLoopManager::the().register_signal(signal_number, move(handler));
|
|
}
|
|
|
|
void EventLoop::unregister_signal(int handler_id)
|
|
{
|
|
EventLoopManager::the().unregister_signal(handler_id);
|
|
}
|
|
|
|
intptr_t EventLoop::register_timer(EventReceiver& object, int milliseconds, bool should_reload)
|
|
{
|
|
return EventLoopManager::the().register_timer(object, milliseconds, should_reload);
|
|
}
|
|
|
|
void EventLoop::unregister_timer(intptr_t timer_id)
|
|
{
|
|
EventLoopManager::the().unregister_timer(timer_id);
|
|
}
|
|
|
|
void EventLoop::register_notifier(Badge<Notifier>, Notifier& notifier)
|
|
{
|
|
EventLoopManager::the().register_notifier(notifier);
|
|
}
|
|
|
|
void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier)
|
|
{
|
|
EventLoopManager::the().unregister_notifier(notifier);
|
|
}
|
|
|
|
void EventLoop::register_process(pid_t pid, ESCAPING Function<void(pid_t)> exit_handler)
|
|
{
|
|
EventLoopManager::the().register_process(pid, move(exit_handler));
|
|
}
|
|
|
|
void EventLoop::unregister_process(pid_t pid)
|
|
{
|
|
EventLoopManager::the().unregister_process(pid);
|
|
}
|
|
|
|
void EventLoop::wake()
|
|
{
|
|
m_impl->wake();
|
|
}
|
|
|
|
void EventLoop::deferred_invoke(Function<void()> invokee)
|
|
{
|
|
m_impl->deferred_invoke(move(invokee));
|
|
}
|
|
|
|
void deferred_invoke(Function<void()> invokee)
|
|
{
|
|
EventLoop::current().deferred_invoke(move(invokee));
|
|
}
|
|
|
|
WeakEventLoopReference::WeakEventLoopReference(EventLoop& event_loop)
|
|
: m_event_loop(&event_loop)
|
|
{
|
|
}
|
|
|
|
void WeakEventLoopReference::revoke()
|
|
{
|
|
Sync::RWLockLocker<Sync::LockMode::Write> locker { m_lock };
|
|
m_event_loop = nullptr;
|
|
}
|
|
|
|
StrongEventLoopReference WeakEventLoopReference::take()
|
|
{
|
|
return StrongEventLoopReference(*this);
|
|
}
|
|
|
|
StrongEventLoopReference::StrongEventLoopReference(WeakEventLoopReference& event_loop_weak)
|
|
{
|
|
event_loop_weak.m_lock.lock_read();
|
|
m_event_loop_weak = &event_loop_weak;
|
|
}
|
|
|
|
StrongEventLoopReference::~StrongEventLoopReference()
|
|
{
|
|
m_event_loop_weak->m_lock.unlock_read();
|
|
}
|
|
|
|
bool StrongEventLoopReference::is_alive() const
|
|
{
|
|
return m_event_loop_weak->m_event_loop != nullptr;
|
|
}
|
|
|
|
StrongEventLoopReference::operator bool() const
|
|
{
|
|
return is_alive();
|
|
}
|
|
|
|
EventLoop* StrongEventLoopReference::operator*() const
|
|
{
|
|
VERIFY(is_alive());
|
|
return m_event_loop_weak->m_event_loop;
|
|
}
|
|
|
|
EventLoop* StrongEventLoopReference::operator->() const
|
|
{
|
|
VERIFY(is_alive());
|
|
return m_event_loop_weak->m_event_loop;
|
|
}
|
|
|
|
}
|