mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 06:02:44 +00:00 
			
		
		
		
	LibCore+Ladybird: Add EventLoopManager interface for persistent state
Things such as timers and notifiers aren't specific to one instance of Core::EventLoop, so let's not tie them down to EventLoopImplementation. Instead, move those APIs + signals & a few other things to a new EventLoopManager interface. EventLoopManager also knows how to create a new EventLoopImplementation object.
This commit is contained in:
		
							parent
							
								
									c21eb30a2b
								
							
						
					
					
						commit
						7b963e1e98
					
				
					 11 changed files with 177 additions and 118 deletions
				
			
		|  | @ -35,11 +35,6 @@ struct ThreadData { | |||
| 
 | ||||
| EventLoopImplementationQt::EventLoopImplementationQt() | ||||
| { | ||||
|     m_process_core_events_timer.setSingleShot(true); | ||||
|     m_process_core_events_timer.setInterval(0); | ||||
|     QObject::connect(&m_process_core_events_timer, &QTimer::timeout, [] { | ||||
|         Core::ThreadEventQueue::current().process(); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| EventLoopImplementationQt::~EventLoopImplementationQt() = default; | ||||
|  | @ -79,7 +74,7 @@ void EventLoopImplementationQt::wake() | |||
|         m_event_loop.wakeUp(); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationQt::deferred_invoke(Function<void()> function) | ||||
| void EventLoopManagerQt::deferred_invoke(Function<void()> function) | ||||
| { | ||||
|     VERIFY(function); | ||||
|     QTimer::singleShot(0, [function = move(function)] { | ||||
|  | @ -97,7 +92,7 @@ static void qt_timer_fired(int timer_id, Core::TimerShouldFireWhenNotVisible sho | |||
|     object.dispatch_event(event); | ||||
| } | ||||
| 
 | ||||
| int EventLoopImplementationQt::register_timer(Core::Object& object, int milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible) | ||||
| int EventLoopManagerQt::register_timer(Core::Object& object, int milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible) | ||||
| { | ||||
|     auto& thread_data = ThreadData::the(); | ||||
|     auto timer = make<QTimer>(); | ||||
|  | @ -116,7 +111,7 @@ int EventLoopImplementationQt::register_timer(Core::Object& object, int millisec | |||
|     return timer_id; | ||||
| } | ||||
| 
 | ||||
| bool EventLoopImplementationQt::unregister_timer(int timer_id) | ||||
| bool EventLoopManagerQt::unregister_timer(int timer_id) | ||||
| { | ||||
|     auto& thread_data = ThreadData::the(); | ||||
|     thread_data.timer_id_allocator.deallocate(timer_id); | ||||
|  | @ -129,7 +124,7 @@ static void qt_notifier_activated(Core::Notifier& notifier) | |||
|     notifier.dispatch_event(event); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationQt::register_notifier(Core::Notifier& notifier) | ||||
| void EventLoopManagerQt::register_notifier(Core::Notifier& notifier) | ||||
| { | ||||
|     QSocketNotifier::Type type; | ||||
|     switch (notifier.type()) { | ||||
|  | @ -150,14 +145,34 @@ void EventLoopImplementationQt::register_notifier(Core::Notifier& notifier) | |||
|     ThreadData::the().notifiers.set(¬ifier, move(socket_notifier)); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationQt::unregister_notifier(Core::Notifier& notifier) | ||||
| void EventLoopManagerQt::unregister_notifier(Core::Notifier& notifier) | ||||
| { | ||||
|     ThreadData::the().notifiers.remove(¬ifier); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationQt::did_post_event() | ||||
| void EventLoopManagerQt::did_post_event() | ||||
| { | ||||
|     m_process_core_events_timer.start(); | ||||
| } | ||||
| 
 | ||||
| EventLoopManagerQt::EventLoopManagerQt() | ||||
| { | ||||
|     m_process_core_events_timer.setSingleShot(true); | ||||
|     m_process_core_events_timer.setInterval(0); | ||||
|     QObject::connect(&m_process_core_events_timer, &QTimer::timeout, [] { | ||||
|         Core::ThreadEventQueue::current().process(); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| EventLoopManagerQt::~EventLoopManagerQt() = default; | ||||
| 
 | ||||
| void EventLoopManagerQt::wake() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerQt::make_implementation() | ||||
| { | ||||
|     return adopt_own(*new EventLoopImplementationQt); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -16,16 +16,11 @@ | |||
| 
 | ||||
| namespace Ladybird { | ||||
| 
 | ||||
| class EventLoopImplementationQt final : public Core::EventLoopImplementation { | ||||
| class EventLoopManagerQt final : public Core::EventLoopManager { | ||||
| public: | ||||
|     static NonnullOwnPtr<EventLoopImplementationQt> create() { return adopt_own(*new EventLoopImplementationQt); } | ||||
| 
 | ||||
|     virtual ~EventLoopImplementationQt() override; | ||||
| 
 | ||||
|     virtual int exec() override; | ||||
|     virtual size_t pump(PumpMode) override; | ||||
|     virtual void quit(int) override; | ||||
|     virtual void wake() override; | ||||
|     EventLoopManagerQt(); | ||||
|     virtual ~EventLoopManagerQt() override; | ||||
|     virtual NonnullOwnPtr<Core::EventLoopImplementation> make_implementation() override; | ||||
| 
 | ||||
|     virtual void deferred_invoke(Function<void()>) override; | ||||
| 
 | ||||
|  | @ -37,21 +32,41 @@ public: | |||
| 
 | ||||
|     virtual void did_post_event() override; | ||||
| 
 | ||||
|     virtual void wake() override; | ||||
| 
 | ||||
|     // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them.
 | ||||
|     virtual int register_signal(int, Function<void(int)>) override { return 0; } | ||||
|     virtual void unregister_signal(int) override { } | ||||
| 
 | ||||
| private: | ||||
|     QTimer m_process_core_events_timer; | ||||
| }; | ||||
| 
 | ||||
| class EventLoopImplementationQt final : public Core::EventLoopImplementation { | ||||
| public: | ||||
|     static NonnullOwnPtr<EventLoopImplementationQt> create() { return adopt_own(*new EventLoopImplementationQt); } | ||||
| 
 | ||||
|     virtual ~EventLoopImplementationQt() override; | ||||
| 
 | ||||
|     virtual int exec() override; | ||||
|     virtual size_t pump(PumpMode) override; | ||||
|     virtual void quit(int) override; | ||||
|     virtual void wake() override; | ||||
| 
 | ||||
|     // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them.
 | ||||
|     virtual void unquit() override { } | ||||
|     virtual bool was_exit_requested() const override { return false; } | ||||
|     virtual void notify_forked_and_in_child() override { } | ||||
|     virtual int register_signal(int, Function<void(int)>) override { return 0; } | ||||
|     virtual void unregister_signal(int) override { } | ||||
| 
 | ||||
|     void set_main_loop() { m_main_loop = true; } | ||||
| 
 | ||||
| private: | ||||
|     friend class EventLoopManagerQt; | ||||
| 
 | ||||
|     EventLoopImplementationQt(); | ||||
|     bool is_main_loop() const { return m_main_loop; } | ||||
| 
 | ||||
|     QEventLoop m_event_loop; | ||||
|     QTimer m_process_core_events_timer; | ||||
|     bool m_main_loop { false }; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | |||
| { | ||||
|     QGuiApplication app(arguments.argc, arguments.argv); | ||||
| 
 | ||||
|     Core::EventLoop::make_implementation = Ladybird::EventLoopImplementationQt::create; | ||||
|     Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt); | ||||
|     Core::EventLoop event_loop; | ||||
| 
 | ||||
|     platform_init(); | ||||
|  |  | |||
|  | @ -54,7 +54,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | |||
| { | ||||
|     QApplication app(arguments.argc, arguments.argv); | ||||
| 
 | ||||
|     Core::EventLoop::make_implementation = Ladybird::EventLoopImplementationQt::create; | ||||
|     Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt); | ||||
|     Core::EventLoop event_loop; | ||||
|     static_cast<Ladybird::EventLoopImplementationQt&>(event_loop.impl()).set_main_loop(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,16 +24,10 @@ Vector<EventLoop&>& event_loop_stack() | |||
|         s_event_loop_stack = new Vector<EventLoop&>; | ||||
|     return *s_event_loop_stack; | ||||
| } | ||||
| bool has_event_loop() | ||||
| { | ||||
|     return !event_loop_stack().is_empty(); | ||||
| } | ||||
| } | ||||
| 
 | ||||
| Function<NonnullOwnPtr<EventLoopImplementation>()> EventLoop::make_implementation = EventLoopImplementationUnix::create; | ||||
| 
 | ||||
| EventLoop::EventLoop() | ||||
|     : m_impl(make_implementation()) | ||||
|     : m_impl(EventLoopManager::the().make_implementation()) | ||||
| { | ||||
|     if (event_loop_stack().is_empty()) { | ||||
|         event_loop_stack().append(*this); | ||||
|  | @ -94,7 +88,7 @@ size_t EventLoop::pump(WaitMode mode) | |||
| 
 | ||||
| void EventLoop::post_event(Object& receiver, NonnullOwnPtr<Event>&& event) | ||||
| { | ||||
|     m_impl->post_event(receiver, move(event)); | ||||
|     EventLoopManager::the().post_event(receiver, move(event)); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::add_job(NonnullRefPtr<Promise<NonnullRefPtr<Object>>> job_promise) | ||||
|  | @ -104,16 +98,12 @@ void EventLoop::add_job(NonnullRefPtr<Promise<NonnullRefPtr<Object>>> job_promis | |||
| 
 | ||||
| int EventLoop::register_signal(int signal_number, Function<void(int)> handler) | ||||
| { | ||||
|     if (!has_event_loop()) | ||||
|         return 0; | ||||
|     return current().m_impl->register_signal(signal_number, move(handler)); | ||||
|     return EventLoopManager::the().register_signal(signal_number, move(handler)); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::unregister_signal(int handler_id) | ||||
| { | ||||
|     if (!has_event_loop()) | ||||
|         return; | ||||
|     current().m_impl->unregister_signal(handler_id); | ||||
|     EventLoopManager::the().unregister_signal(handler_id); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::notify_forked(ForkEvent) | ||||
|  | @ -123,30 +113,22 @@ void EventLoop::notify_forked(ForkEvent) | |||
| 
 | ||||
| int EventLoop::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible) | ||||
| { | ||||
|     if (!has_event_loop()) | ||||
|         return 0; | ||||
|     return current().m_impl->register_timer(object, milliseconds, should_reload, fire_when_not_visible); | ||||
|     return EventLoopManager::the().register_timer(object, milliseconds, should_reload, fire_when_not_visible); | ||||
| } | ||||
| 
 | ||||
| bool EventLoop::unregister_timer(int timer_id) | ||||
| { | ||||
|     if (!has_event_loop()) | ||||
|         return false; | ||||
|     return current().m_impl->unregister_timer(timer_id); | ||||
|     return EventLoopManager::the().unregister_timer(timer_id); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::register_notifier(Badge<Notifier>, Notifier& notifier) | ||||
| { | ||||
|     if (!has_event_loop()) | ||||
|         return; | ||||
|     current().m_impl->register_notifier(notifier); | ||||
|     EventLoopManager::the().register_notifier(notifier); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier) | ||||
| { | ||||
|     if (!has_event_loop()) | ||||
|         return; | ||||
|     current().m_impl->unregister_notifier(notifier); | ||||
|     EventLoopManager::the().unregister_notifier(notifier); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::wake() | ||||
|  | @ -170,9 +152,4 @@ bool EventLoop::was_exit_requested() const | |||
|     return m_impl->was_exit_requested(); | ||||
| } | ||||
| 
 | ||||
| void EventLoop::did_post_event(Badge<Core::ThreadEventQueue>) | ||||
| { | ||||
|     m_impl->did_post_event(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -94,8 +94,6 @@ public: | |||
| 
 | ||||
|     static EventLoop& current(); | ||||
| 
 | ||||
|     static Function<NonnullOwnPtr<EventLoopImplementation>()> make_implementation; | ||||
| 
 | ||||
|     void did_post_event(Badge<ThreadEventQueue>); | ||||
|     EventLoopImplementation& impl() { return *m_impl; } | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,18 +7,36 @@ | |||
| #include <AK/NonnullOwnPtr.h> | ||||
| #include <LibCore/Event.h> | ||||
| #include <LibCore/EventLoopImplementation.h> | ||||
| #include <LibCore/EventLoopImplementationUnix.h> | ||||
| #include <LibCore/ThreadEventQueue.h> | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| EventLoopImplementation::EventLoopImplementation() | ||||
| EventLoopImplementation::EventLoopImplementation() = default; | ||||
| 
 | ||||
| EventLoopImplementation::~EventLoopImplementation() = default; | ||||
| 
 | ||||
| static EventLoopManager* s_event_loop_manager; | ||||
| EventLoopManager& EventLoopManager::the() | ||||
| { | ||||
|     if (!s_event_loop_manager) | ||||
|         s_event_loop_manager = new EventLoopManagerUnix; | ||||
|     return *s_event_loop_manager; | ||||
| } | ||||
| 
 | ||||
| void EventLoopManager::install(Core::EventLoopManager& manager) | ||||
| { | ||||
|     s_event_loop_manager = &manager; | ||||
| } | ||||
| 
 | ||||
| EventLoopManager::EventLoopManager() | ||||
|     : m_thread_event_queue(ThreadEventQueue::current()) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| EventLoopImplementation::~EventLoopImplementation() = default; | ||||
| EventLoopManager::~EventLoopManager() = default; | ||||
| 
 | ||||
| void EventLoopImplementation::post_event(Object& receiver, NonnullOwnPtr<Event>&& event) | ||||
| void EventLoopManager::post_event(Object& receiver, NonnullOwnPtr<Event>&& event) | ||||
| { | ||||
|     m_thread_event_queue.post_event(receiver, move(event)); | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,8 +11,40 @@ | |||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| class EventLoopImplementation; | ||||
| class ThreadEventQueue; | ||||
| 
 | ||||
| class EventLoopManager { | ||||
| public: | ||||
|     static EventLoopManager& the(); | ||||
|     static void install(EventLoopManager&); | ||||
| 
 | ||||
|     virtual ~EventLoopManager(); | ||||
| 
 | ||||
|     virtual NonnullOwnPtr<EventLoopImplementation> make_implementation() = 0; | ||||
| 
 | ||||
|     virtual int register_timer(Object&, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible) = 0; | ||||
|     virtual bool unregister_timer(int timer_id) = 0; | ||||
| 
 | ||||
|     virtual void register_notifier(Notifier&) = 0; | ||||
|     virtual void unregister_notifier(Notifier&) = 0; | ||||
| 
 | ||||
|     void post_event(Object& receiver, NonnullOwnPtr<Event>&&); | ||||
|     virtual void did_post_event() = 0; | ||||
| 
 | ||||
|     virtual void deferred_invoke(Function<void()>) = 0; | ||||
| 
 | ||||
|     // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them.
 | ||||
|     virtual int register_signal(int signal_number, Function<void(int)> handler) = 0; | ||||
|     virtual void unregister_signal(int handler_id) = 0; | ||||
| 
 | ||||
|     virtual void wake() = 0; | ||||
| 
 | ||||
| protected: | ||||
|     EventLoopManager(); | ||||
|     ThreadEventQueue& m_thread_event_queue; | ||||
| }; | ||||
| 
 | ||||
| class EventLoopImplementation { | ||||
| public: | ||||
|     virtual ~EventLoopImplementation(); | ||||
|  | @ -22,34 +54,18 @@ public: | |||
|         DontWaitForEvents, | ||||
|     }; | ||||
| 
 | ||||
|     void post_event(Object& receiver, NonnullOwnPtr<Event>&&); | ||||
| 
 | ||||
|     virtual int exec() = 0; | ||||
|     virtual size_t pump(PumpMode) = 0; | ||||
|     virtual void quit(int) = 0; | ||||
|     virtual void wake() = 0; | ||||
| 
 | ||||
|     virtual void deferred_invoke(Function<void()>) = 0; | ||||
| 
 | ||||
|     virtual int register_timer(Object&, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible) = 0; | ||||
|     virtual bool unregister_timer(int timer_id) = 0; | ||||
| 
 | ||||
|     virtual void register_notifier(Notifier&) = 0; | ||||
|     virtual void unregister_notifier(Notifier&) = 0; | ||||
| 
 | ||||
|     virtual void did_post_event() = 0; | ||||
| 
 | ||||
|     // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them.
 | ||||
|     virtual void unquit() = 0; | ||||
|     virtual bool was_exit_requested() const = 0; | ||||
|     virtual void notify_forked_and_in_child() = 0; | ||||
|     virtual int register_signal(int signal_number, Function<void(int)> handler) = 0; | ||||
|     virtual void unregister_signal(int handler_id) = 0; | ||||
| 
 | ||||
| protected: | ||||
|     EventLoopImplementation(); | ||||
| 
 | ||||
|     ThreadEventQueue& m_thread_event_queue; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -105,11 +105,8 @@ int EventLoopImplementationUnix::exec() | |||
| 
 | ||||
| size_t EventLoopImplementationUnix::pump(PumpMode mode) | ||||
| { | ||||
|     // We can only pump the event loop of the current thread.
 | ||||
|     VERIFY(&m_thread_event_queue == &ThreadEventQueue::current()); | ||||
| 
 | ||||
|     wait_for_events(mode); | ||||
|     return m_thread_event_queue.process(); | ||||
|     static_cast<EventLoopManagerUnix&>(EventLoopManager::the()).wait_for_events(mode); | ||||
|     return ThreadEventQueue::current().process(); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::quit(int code) | ||||
|  | @ -135,14 +132,20 @@ void EventLoopImplementationUnix::wake() | |||
|     MUST(Core::System::write((*m_wake_pipe_fds)[1], { &wake_event, sizeof(wake_event) })); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::deferred_invoke(Function<void()> invokee) | ||||
| void EventLoopManagerUnix::wake() | ||||
| { | ||||
|     int wake_event = 0; | ||||
|     MUST(Core::System::write(ThreadData::the().wake_pipe_fds[1], { &wake_event, sizeof(wake_event) })); | ||||
| } | ||||
| 
 | ||||
| void EventLoopManagerUnix::deferred_invoke(Function<void()> invokee) | ||||
| { | ||||
|     // FIXME: Get rid of the useless DeferredInvocationContext object.
 | ||||
|     auto context = DeferredInvocationContext::construct(); | ||||
|     post_event(context, make<DeferredInvocationEvent>(context, move(invokee))); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::wait_for_events(PumpMode mode) | ||||
| void EventLoopManagerUnix::wait_for_events(EventLoopImplementation::PumpMode mode) | ||||
| { | ||||
|     auto& thread_data = ThreadData::the(); | ||||
| 
 | ||||
|  | @ -177,7 +180,7 @@ retry: | |||
|     Time now; | ||||
|     struct timeval timeout = { 0, 0 }; | ||||
|     bool should_wait_forever = false; | ||||
|     if (mode == PumpMode::WaitForEvents && !has_pending_events) { | ||||
|     if (mode == EventLoopImplementation::PumpMode::WaitForEvents && !has_pending_events) { | ||||
|         auto next_timer_expiration = get_next_timer_expiration(); | ||||
|         if (next_timer_expiration.has_value()) { | ||||
|             now = Time::now_monotonic_coarse(); | ||||
|  | @ -196,11 +199,8 @@ try_select_again: | |||
|     // Because POSIX, we might spuriously return from select() with EINTR; just select again.
 | ||||
|     if (marked_fd_count < 0) { | ||||
|         int saved_errno = errno; | ||||
|         if (saved_errno == EINTR) { | ||||
|             if (m_exit_requested) | ||||
|                 return; | ||||
|         if (saved_errno == EINTR) | ||||
|             goto try_select_again; | ||||
|         } | ||||
|         dbgln("EventLoopImplementationUnix::wait_for_events: {} ({}: {})", marked_fd_count, saved_errno, strerror(saved_errno)); | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
|  | @ -329,7 +329,7 @@ inline SignalHandlersInfo* signals_info() | |||
|     return s_signals.ptr(); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::dispatch_signal(int signal_number) | ||||
| void EventLoopManagerUnix::dispatch_signal(int signal_number) | ||||
| { | ||||
|     auto& info = *signals_info(); | ||||
|     auto handlers = info.signal_handlers.find(signal_number); | ||||
|  | @ -355,7 +355,7 @@ void EventLoopImplementationUnix::notify_forked_and_in_child() | |||
|     thread_data.pid = getpid(); | ||||
| } | ||||
| 
 | ||||
| Optional<Time> EventLoopImplementationUnix::get_next_timer_expiration() | ||||
| Optional<Time> EventLoopManagerUnix::get_next_timer_expiration() | ||||
| { | ||||
|     auto now = Time::now_monotonic_coarse(); | ||||
|     Optional<Time> soonest {}; | ||||
|  | @ -438,7 +438,7 @@ bool SignalHandlers::remove(int handler_id) | |||
|     return m_handlers.remove(handler_id); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::handle_signal(int signal_number) | ||||
| void EventLoopManagerUnix::handle_signal(int signal_number) | ||||
| { | ||||
|     VERIFY(signal_number != 0); | ||||
|     auto& thread_data = ThreadData::the(); | ||||
|  | @ -457,13 +457,13 @@ void EventLoopImplementationUnix::handle_signal(int signal_number) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| int EventLoopImplementationUnix::register_signal(int signal_number, Function<void(int)> handler) | ||||
| int EventLoopManagerUnix::register_signal(int signal_number, Function<void(int)> handler) | ||||
| { | ||||
|     VERIFY(signal_number != 0); | ||||
|     auto& info = *signals_info(); | ||||
|     auto handlers = info.signal_handlers.find(signal_number); | ||||
|     if (handlers == info.signal_handlers.end()) { | ||||
|         auto signal_handlers = adopt_ref(*new SignalHandlers(signal_number, EventLoopImplementationUnix::handle_signal)); | ||||
|         auto signal_handlers = adopt_ref(*new SignalHandlers(signal_number, EventLoopManagerUnix::handle_signal)); | ||||
|         auto handler_id = signal_handlers->add(move(handler)); | ||||
|         info.signal_handlers.set(signal_number, move(signal_handlers)); | ||||
|         return handler_id; | ||||
|  | @ -472,7 +472,7 @@ int EventLoopImplementationUnix::register_signal(int signal_number, Function<voi | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::unregister_signal(int handler_id) | ||||
| void EventLoopManagerUnix::unregister_signal(int handler_id) | ||||
| { | ||||
|     VERIFY(handler_id != 0); | ||||
|     int remove_signal_number = 0; | ||||
|  | @ -489,7 +489,7 @@ void EventLoopImplementationUnix::unregister_signal(int handler_id) | |||
|         info.signal_handlers.remove(remove_signal_number); | ||||
| } | ||||
| 
 | ||||
| int EventLoopImplementationUnix::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible) | ||||
| int EventLoopManagerUnix::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible) | ||||
| { | ||||
|     VERIFY(milliseconds >= 0); | ||||
|     auto& thread_data = ThreadData::the(); | ||||
|  | @ -505,25 +505,32 @@ int EventLoopImplementationUnix::register_timer(Object& object, int milliseconds | |||
|     return timer_id; | ||||
| } | ||||
| 
 | ||||
| bool EventLoopImplementationUnix::unregister_timer(int timer_id) | ||||
| bool EventLoopManagerUnix::unregister_timer(int timer_id) | ||||
| { | ||||
|     auto& thread_data = ThreadData::the(); | ||||
|     thread_data.id_allocator.deallocate(timer_id); | ||||
|     return thread_data.timers.remove(timer_id); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::register_notifier(Notifier& notifier) | ||||
| void EventLoopManagerUnix::register_notifier(Notifier& notifier) | ||||
| { | ||||
|     ThreadData::the().notifiers.set(¬ifier); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::unregister_notifier(Notifier& notifier) | ||||
| void EventLoopManagerUnix::unregister_notifier(Notifier& notifier) | ||||
| { | ||||
|     ThreadData::the().notifiers.remove(¬ifier); | ||||
| } | ||||
| 
 | ||||
| void EventLoopImplementationUnix::did_post_event() | ||||
| void EventLoopManagerUnix::did_post_event() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| EventLoopManagerUnix::~EventLoopManagerUnix() = default; | ||||
| 
 | ||||
| NonnullOwnPtr<EventLoopImplementation> EventLoopManagerUnix::make_implementation() | ||||
| { | ||||
|     return adopt_own(*new EventLoopImplementationUnix); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -10,6 +10,35 @@ | |||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| class EventLoopManagerUnix final : public EventLoopManager { | ||||
| public: | ||||
|     virtual ~EventLoopManagerUnix() override; | ||||
| 
 | ||||
|     virtual NonnullOwnPtr<EventLoopImplementation> make_implementation() override; | ||||
| 
 | ||||
|     virtual void deferred_invoke(Function<void()>) override; | ||||
| 
 | ||||
|     virtual int register_timer(Object&, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible) override; | ||||
|     virtual bool unregister_timer(int timer_id) override; | ||||
| 
 | ||||
|     virtual void register_notifier(Notifier&) override; | ||||
|     virtual void unregister_notifier(Notifier&) override; | ||||
| 
 | ||||
|     virtual void did_post_event() override; | ||||
| 
 | ||||
|     virtual int register_signal(int signal_number, Function<void(int)> handler) override; | ||||
|     virtual void unregister_signal(int handler_id) override; | ||||
| 
 | ||||
|     virtual void wake() override; | ||||
| 
 | ||||
|     void wait_for_events(EventLoopImplementation::PumpMode); | ||||
|     static Optional<Time> get_next_timer_expiration(); | ||||
| 
 | ||||
| private: | ||||
|     void dispatch_signal(int signal_number); | ||||
|     static void handle_signal(int signal_number); | ||||
| }; | ||||
| 
 | ||||
| class EventLoopImplementationUnix final : public EventLoopImplementation { | ||||
| public: | ||||
|     static NonnullOwnPtr<EventLoopImplementationUnix> create() { return make<EventLoopImplementationUnix>(); } | ||||
|  | @ -23,28 +52,11 @@ public: | |||
| 
 | ||||
|     virtual void wake() override; | ||||
| 
 | ||||
|     virtual void deferred_invoke(Function<void()>) override; | ||||
| 
 | ||||
|     virtual int register_timer(Object&, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible) override; | ||||
|     virtual bool unregister_timer(int timer_id) override; | ||||
| 
 | ||||
|     virtual void register_notifier(Notifier&) override; | ||||
|     virtual void unregister_notifier(Notifier&) override; | ||||
| 
 | ||||
|     virtual void did_post_event() override; | ||||
| 
 | ||||
|     virtual void unquit() override; | ||||
|     virtual bool was_exit_requested() const override; | ||||
|     virtual void notify_forked_and_in_child() override; | ||||
|     virtual int register_signal(int signal_number, Function<void(int)> handler) override; | ||||
|     virtual void unregister_signal(int handler_id) override; | ||||
| 
 | ||||
| private: | ||||
|     void wait_for_events(PumpMode); | ||||
|     void dispatch_signal(int signal_number); | ||||
|     static void handle_signal(int signal_number); | ||||
|     static Optional<Time> get_next_timer_expiration(); | ||||
| 
 | ||||
|     bool m_exit_requested { false }; | ||||
|     int m_exit_code { 0 }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ | |||
| 
 | ||||
| #include <AK/Vector.h> | ||||
| #include <LibCore/DeferredInvocationContext.h> | ||||
| #include <LibCore/EventLoopImplementation.h> | ||||
| #include <LibCore/Object.h> | ||||
| #include <LibCore/Promise.h> | ||||
| #include <LibCore/ThreadEventQueue.h> | ||||
|  | @ -66,7 +67,7 @@ void ThreadEventQueue::post_event(Core::Object& receiver, NonnullOwnPtr<Core::Ev | |||
|         Threading::MutexLocker lock(m_private->mutex); | ||||
|         m_private->queued_events.empend(receiver, move(event)); | ||||
|     } | ||||
|     Core::EventLoop::current().did_post_event({}); | ||||
|     Core::EventLoopManager::the().did_post_event(); | ||||
| } | ||||
| 
 | ||||
| void ThreadEventQueue::add_job(NonnullRefPtr<Promise<NonnullRefPtr<Object>>> promise) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling