/* * Copyright (c) 2018-2023, Andreas Kling * Copyright (c) 2022, kleines Filmröllchen * Copyright (c) 2022, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include namespace Core { namespace { OwnPtr>& event_loop_stack_uninitialized() { thread_local OwnPtr> s_event_loop_stack = nullptr; return s_event_loop_stack; } Vector& event_loop_stack() { auto& the_stack = event_loop_stack_uninitialized(); if (the_stack == nullptr) the_stack = make>(); 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 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 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 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) { EventLoopManager::the().register_notifier(notifier); } void EventLoop::unregister_notifier(Badge, Notifier& notifier) { EventLoopManager::the().unregister_notifier(notifier); } void EventLoop::wake() { m_impl->wake(); } void EventLoop::deferred_invoke(Function invokee) { m_impl->deferred_invoke(move(invokee)); } void deferred_invoke(Function invokee) { EventLoop::current().deferred_invoke(move(invokee)); } WeakEventLoopReference::WeakEventLoopReference(EventLoop& event_loop) : m_event_loop(&event_loop) { } void WeakEventLoopReference::revoke() { Threading::RWLockLocker 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(); } 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; } }