mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 05:52:46 +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() | 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; | EventLoopImplementationQt::~EventLoopImplementationQt() = default; | ||||||
|  | @ -79,7 +74,7 @@ void EventLoopImplementationQt::wake() | ||||||
|         m_event_loop.wakeUp(); |         m_event_loop.wakeUp(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoopImplementationQt::deferred_invoke(Function<void()> function) | void EventLoopManagerQt::deferred_invoke(Function<void()> function) | ||||||
| { | { | ||||||
|     VERIFY(function); |     VERIFY(function); | ||||||
|     QTimer::singleShot(0, [function = move(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); |     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& thread_data = ThreadData::the(); | ||||||
|     auto timer = make<QTimer>(); |     auto timer = make<QTimer>(); | ||||||
|  | @ -116,7 +111,7 @@ int EventLoopImplementationQt::register_timer(Core::Object& object, int millisec | ||||||
|     return timer_id; |     return timer_id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool EventLoopImplementationQt::unregister_timer(int timer_id) | bool EventLoopManagerQt::unregister_timer(int timer_id) | ||||||
| { | { | ||||||
|     auto& thread_data = ThreadData::the(); |     auto& thread_data = ThreadData::the(); | ||||||
|     thread_data.timer_id_allocator.deallocate(timer_id); |     thread_data.timer_id_allocator.deallocate(timer_id); | ||||||
|  | @ -129,7 +124,7 @@ static void qt_notifier_activated(Core::Notifier& notifier) | ||||||
|     notifier.dispatch_event(event); |     notifier.dispatch_event(event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoopImplementationQt::register_notifier(Core::Notifier& notifier) | void EventLoopManagerQt::register_notifier(Core::Notifier& notifier) | ||||||
| { | { | ||||||
|     QSocketNotifier::Type type; |     QSocketNotifier::Type type; | ||||||
|     switch (notifier.type()) { |     switch (notifier.type()) { | ||||||
|  | @ -150,14 +145,34 @@ void EventLoopImplementationQt::register_notifier(Core::Notifier& notifier) | ||||||
|     ThreadData::the().notifiers.set(¬ifier, move(socket_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); |     ThreadData::the().notifiers.remove(¬ifier); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoopImplementationQt::did_post_event() | void EventLoopManagerQt::did_post_event() | ||||||
| { | { | ||||||
|     m_process_core_events_timer.start(); |     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 { | namespace Ladybird { | ||||||
| 
 | 
 | ||||||
| class EventLoopImplementationQt final : public Core::EventLoopImplementation { | class EventLoopManagerQt final : public Core::EventLoopManager { | ||||||
| public: | public: | ||||||
|     static NonnullOwnPtr<EventLoopImplementationQt> create() { return adopt_own(*new EventLoopImplementationQt); } |     EventLoopManagerQt(); | ||||||
| 
 |     virtual ~EventLoopManagerQt() override; | ||||||
|     virtual ~EventLoopImplementationQt() override; |     virtual NonnullOwnPtr<Core::EventLoopImplementation> make_implementation() override; | ||||||
| 
 |  | ||||||
|     virtual int exec() override; |  | ||||||
|     virtual size_t pump(PumpMode) override; |  | ||||||
|     virtual void quit(int) override; |  | ||||||
|     virtual void wake() override; |  | ||||||
| 
 | 
 | ||||||
|     virtual void deferred_invoke(Function<void()>) override; |     virtual void deferred_invoke(Function<void()>) override; | ||||||
| 
 | 
 | ||||||
|  | @ -37,21 +32,41 @@ public: | ||||||
| 
 | 
 | ||||||
|     virtual void did_post_event() override; |     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.
 |     // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them.
 | ||||||
|     virtual void unquit() override { } |     virtual void unquit() override { } | ||||||
|     virtual bool was_exit_requested() const override { return false; } |     virtual bool was_exit_requested() const override { return false; } | ||||||
|     virtual void notify_forked_and_in_child() override { } |     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; } |     void set_main_loop() { m_main_loop = true; } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     friend class EventLoopManagerQt; | ||||||
|  | 
 | ||||||
|     EventLoopImplementationQt(); |     EventLoopImplementationQt(); | ||||||
|     bool is_main_loop() const { return m_main_loop; } |     bool is_main_loop() const { return m_main_loop; } | ||||||
| 
 | 
 | ||||||
|     QEventLoop m_event_loop; |     QEventLoop m_event_loop; | ||||||
|     QTimer m_process_core_events_timer; |  | ||||||
|     bool m_main_loop { false }; |     bool m_main_loop { false }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,7 +40,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||||
| { | { | ||||||
|     QGuiApplication app(arguments.argc, arguments.argv); |     QGuiApplication app(arguments.argc, arguments.argv); | ||||||
| 
 | 
 | ||||||
|     Core::EventLoop::make_implementation = Ladybird::EventLoopImplementationQt::create; |     Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt); | ||||||
|     Core::EventLoop event_loop; |     Core::EventLoop event_loop; | ||||||
| 
 | 
 | ||||||
|     platform_init(); |     platform_init(); | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | ||||||
| { | { | ||||||
|     QApplication app(arguments.argc, arguments.argv); |     QApplication app(arguments.argc, arguments.argv); | ||||||
| 
 | 
 | ||||||
|     Core::EventLoop::make_implementation = Ladybird::EventLoopImplementationQt::create; |     Core::EventLoopManager::install(*new Ladybird::EventLoopManagerQt); | ||||||
|     Core::EventLoop event_loop; |     Core::EventLoop event_loop; | ||||||
|     static_cast<Ladybird::EventLoopImplementationQt&>(event_loop.impl()).set_main_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&>; |         s_event_loop_stack = new Vector<EventLoop&>; | ||||||
|     return *s_event_loop_stack; |     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() | EventLoop::EventLoop() | ||||||
|     : m_impl(make_implementation()) |     : m_impl(EventLoopManager::the().make_implementation()) | ||||||
| { | { | ||||||
|     if (event_loop_stack().is_empty()) { |     if (event_loop_stack().is_empty()) { | ||||||
|         event_loop_stack().append(*this); |         event_loop_stack().append(*this); | ||||||
|  | @ -94,7 +88,7 @@ size_t EventLoop::pump(WaitMode mode) | ||||||
| 
 | 
 | ||||||
| void EventLoop::post_event(Object& receiver, NonnullOwnPtr<Event>&& event) | 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) | 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) | int EventLoop::register_signal(int signal_number, Function<void(int)> handler) | ||||||
| { | { | ||||||
|     if (!has_event_loop()) |     return EventLoopManager::the().register_signal(signal_number, move(handler)); | ||||||
|         return 0; |  | ||||||
|     return current().m_impl->register_signal(signal_number, move(handler)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoop::unregister_signal(int handler_id) | void EventLoop::unregister_signal(int handler_id) | ||||||
| { | { | ||||||
|     if (!has_event_loop()) |     EventLoopManager::the().unregister_signal(handler_id); | ||||||
|         return; |  | ||||||
|     current().m_impl->unregister_signal(handler_id); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoop::notify_forked(ForkEvent) | 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) | int EventLoop::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible) | ||||||
| { | { | ||||||
|     if (!has_event_loop()) |     return EventLoopManager::the().register_timer(object, milliseconds, should_reload, fire_when_not_visible); | ||||||
|         return 0; |  | ||||||
|     return current().m_impl->register_timer(object, milliseconds, should_reload, fire_when_not_visible); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool EventLoop::unregister_timer(int timer_id) | bool EventLoop::unregister_timer(int timer_id) | ||||||
| { | { | ||||||
|     if (!has_event_loop()) |     return EventLoopManager::the().unregister_timer(timer_id); | ||||||
|         return false; |  | ||||||
|     return current().m_impl->unregister_timer(timer_id); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoop::register_notifier(Badge<Notifier>, Notifier& notifier) | void EventLoop::register_notifier(Badge<Notifier>, Notifier& notifier) | ||||||
| { | { | ||||||
|     if (!has_event_loop()) |     EventLoopManager::the().register_notifier(notifier); | ||||||
|         return; |  | ||||||
|     current().m_impl->register_notifier(notifier); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier) | void EventLoop::unregister_notifier(Badge<Notifier>, Notifier& notifier) | ||||||
| { | { | ||||||
|     if (!has_event_loop()) |     EventLoopManager::the().unregister_notifier(notifier); | ||||||
|         return; |  | ||||||
|     current().m_impl->unregister_notifier(notifier); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoop::wake() | void EventLoop::wake() | ||||||
|  | @ -170,9 +152,4 @@ bool EventLoop::was_exit_requested() const | ||||||
|     return m_impl->was_exit_requested(); |     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 EventLoop& current(); | ||||||
| 
 | 
 | ||||||
|     static Function<NonnullOwnPtr<EventLoopImplementation>()> make_implementation; |  | ||||||
| 
 |  | ||||||
|     void did_post_event(Badge<ThreadEventQueue>); |     void did_post_event(Badge<ThreadEventQueue>); | ||||||
|     EventLoopImplementation& impl() { return *m_impl; } |     EventLoopImplementation& impl() { return *m_impl; } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,18 +7,36 @@ | ||||||
| #include <AK/NonnullOwnPtr.h> | #include <AK/NonnullOwnPtr.h> | ||||||
| #include <LibCore/Event.h> | #include <LibCore/Event.h> | ||||||
| #include <LibCore/EventLoopImplementation.h> | #include <LibCore/EventLoopImplementation.h> | ||||||
|  | #include <LibCore/EventLoopImplementationUnix.h> | ||||||
| #include <LibCore/ThreadEventQueue.h> | #include <LibCore/ThreadEventQueue.h> | ||||||
| 
 | 
 | ||||||
| namespace Core { | 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()) |     : 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)); |     m_thread_event_queue.post_event(receiver, move(event)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,8 +11,40 @@ | ||||||
| 
 | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
| 
 | 
 | ||||||
|  | class EventLoopImplementation; | ||||||
| class ThreadEventQueue; | 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 { | class EventLoopImplementation { | ||||||
| public: | public: | ||||||
|     virtual ~EventLoopImplementation(); |     virtual ~EventLoopImplementation(); | ||||||
|  | @ -22,34 +54,18 @@ public: | ||||||
|         DontWaitForEvents, |         DontWaitForEvents, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     void post_event(Object& receiver, NonnullOwnPtr<Event>&&); |  | ||||||
| 
 |  | ||||||
|     virtual int exec() = 0; |     virtual int exec() = 0; | ||||||
|     virtual size_t pump(PumpMode) = 0; |     virtual size_t pump(PumpMode) = 0; | ||||||
|     virtual void quit(int) = 0; |     virtual void quit(int) = 0; | ||||||
|     virtual void wake() = 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.
 |     // FIXME: These APIs only exist for obscure use-cases inside SerenityOS. Try to get rid of them.
 | ||||||
|     virtual void unquit() = 0; |     virtual void unquit() = 0; | ||||||
|     virtual bool was_exit_requested() const = 0; |     virtual bool was_exit_requested() const = 0; | ||||||
|     virtual void notify_forked_and_in_child() = 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: | protected: | ||||||
|     EventLoopImplementation(); |     EventLoopImplementation(); | ||||||
| 
 |  | ||||||
|     ThreadEventQueue& m_thread_event_queue; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -105,11 +105,8 @@ int EventLoopImplementationUnix::exec() | ||||||
| 
 | 
 | ||||||
| size_t EventLoopImplementationUnix::pump(PumpMode mode) | size_t EventLoopImplementationUnix::pump(PumpMode mode) | ||||||
| { | { | ||||||
|     // We can only pump the event loop of the current thread.
 |     static_cast<EventLoopManagerUnix&>(EventLoopManager::the()).wait_for_events(mode); | ||||||
|     VERIFY(&m_thread_event_queue == &ThreadEventQueue::current()); |     return ThreadEventQueue::current().process(); | ||||||
| 
 |  | ||||||
|     wait_for_events(mode); |  | ||||||
|     return m_thread_event_queue.process(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoopImplementationUnix::quit(int code) | 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) })); |     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.
 |     // FIXME: Get rid of the useless DeferredInvocationContext object.
 | ||||||
|     auto context = DeferredInvocationContext::construct(); |     auto context = DeferredInvocationContext::construct(); | ||||||
|     post_event(context, make<DeferredInvocationEvent>(context, move(invokee))); |     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(); |     auto& thread_data = ThreadData::the(); | ||||||
| 
 | 
 | ||||||
|  | @ -177,7 +180,7 @@ retry: | ||||||
|     Time now; |     Time now; | ||||||
|     struct timeval timeout = { 0, 0 }; |     struct timeval timeout = { 0, 0 }; | ||||||
|     bool should_wait_forever = false; |     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(); |         auto next_timer_expiration = get_next_timer_expiration(); | ||||||
|         if (next_timer_expiration.has_value()) { |         if (next_timer_expiration.has_value()) { | ||||||
|             now = Time::now_monotonic_coarse(); |             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.
 |     // Because POSIX, we might spuriously return from select() with EINTR; just select again.
 | ||||||
|     if (marked_fd_count < 0) { |     if (marked_fd_count < 0) { | ||||||
|         int saved_errno = errno; |         int saved_errno = errno; | ||||||
|         if (saved_errno == EINTR) { |         if (saved_errno == EINTR) | ||||||
|             if (m_exit_requested) |  | ||||||
|                 return; |  | ||||||
|             goto try_select_again; |             goto try_select_again; | ||||||
|         } |  | ||||||
|         dbgln("EventLoopImplementationUnix::wait_for_events: {} ({}: {})", marked_fd_count, saved_errno, strerror(saved_errno)); |         dbgln("EventLoopImplementationUnix::wait_for_events: {} ({}: {})", marked_fd_count, saved_errno, strerror(saved_errno)); | ||||||
|         VERIFY_NOT_REACHED(); |         VERIFY_NOT_REACHED(); | ||||||
|     } |     } | ||||||
|  | @ -329,7 +329,7 @@ inline SignalHandlersInfo* signals_info() | ||||||
|     return s_signals.ptr(); |     return s_signals.ptr(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoopImplementationUnix::dispatch_signal(int signal_number) | void EventLoopManagerUnix::dispatch_signal(int signal_number) | ||||||
| { | { | ||||||
|     auto& info = *signals_info(); |     auto& info = *signals_info(); | ||||||
|     auto handlers = info.signal_handlers.find(signal_number); |     auto handlers = info.signal_handlers.find(signal_number); | ||||||
|  | @ -355,7 +355,7 @@ void EventLoopImplementationUnix::notify_forked_and_in_child() | ||||||
|     thread_data.pid = getpid(); |     thread_data.pid = getpid(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Optional<Time> EventLoopImplementationUnix::get_next_timer_expiration() | Optional<Time> EventLoopManagerUnix::get_next_timer_expiration() | ||||||
| { | { | ||||||
|     auto now = Time::now_monotonic_coarse(); |     auto now = Time::now_monotonic_coarse(); | ||||||
|     Optional<Time> soonest {}; |     Optional<Time> soonest {}; | ||||||
|  | @ -438,7 +438,7 @@ bool SignalHandlers::remove(int handler_id) | ||||||
|     return m_handlers.remove(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); |     VERIFY(signal_number != 0); | ||||||
|     auto& thread_data = ThreadData::the(); |     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); |     VERIFY(signal_number != 0); | ||||||
|     auto& info = *signals_info(); |     auto& info = *signals_info(); | ||||||
|     auto handlers = info.signal_handlers.find(signal_number); |     auto handlers = info.signal_handlers.find(signal_number); | ||||||
|     if (handlers == info.signal_handlers.end()) { |     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)); |         auto handler_id = signal_handlers->add(move(handler)); | ||||||
|         info.signal_handlers.set(signal_number, move(signal_handlers)); |         info.signal_handlers.set(signal_number, move(signal_handlers)); | ||||||
|         return handler_id; |         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); |     VERIFY(handler_id != 0); | ||||||
|     int remove_signal_number = 0; |     int remove_signal_number = 0; | ||||||
|  | @ -489,7 +489,7 @@ void EventLoopImplementationUnix::unregister_signal(int handler_id) | ||||||
|         info.signal_handlers.remove(remove_signal_number); |         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); |     VERIFY(milliseconds >= 0); | ||||||
|     auto& thread_data = ThreadData::the(); |     auto& thread_data = ThreadData::the(); | ||||||
|  | @ -505,25 +505,32 @@ int EventLoopImplementationUnix::register_timer(Object& object, int milliseconds | ||||||
|     return timer_id; |     return timer_id; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool EventLoopImplementationUnix::unregister_timer(int timer_id) | bool EventLoopManagerUnix::unregister_timer(int timer_id) | ||||||
| { | { | ||||||
|     auto& thread_data = ThreadData::the(); |     auto& thread_data = ThreadData::the(); | ||||||
|     thread_data.id_allocator.deallocate(timer_id); |     thread_data.id_allocator.deallocate(timer_id); | ||||||
|     return thread_data.timers.remove(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); |     ThreadData::the().notifiers.set(¬ifier); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EventLoopImplementationUnix::unregister_notifier(Notifier& notifier) | void EventLoopManagerUnix::unregister_notifier(Notifier& notifier) | ||||||
| { | { | ||||||
|     ThreadData::the().notifiers.remove(¬ifier); |     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 { | 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 { | class EventLoopImplementationUnix final : public EventLoopImplementation { | ||||||
| public: | public: | ||||||
|     static NonnullOwnPtr<EventLoopImplementationUnix> create() { return make<EventLoopImplementationUnix>(); } |     static NonnullOwnPtr<EventLoopImplementationUnix> create() { return make<EventLoopImplementationUnix>(); } | ||||||
|  | @ -23,28 +52,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     virtual void wake() override; |     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 void unquit() override; | ||||||
|     virtual bool was_exit_requested() const override; |     virtual bool was_exit_requested() const override; | ||||||
|     virtual void notify_forked_and_in_child() 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: | 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 }; |     bool m_exit_requested { false }; | ||||||
|     int m_exit_code { 0 }; |     int m_exit_code { 0 }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <AK/Vector.h> | #include <AK/Vector.h> | ||||||
| #include <LibCore/DeferredInvocationContext.h> | #include <LibCore/DeferredInvocationContext.h> | ||||||
|  | #include <LibCore/EventLoopImplementation.h> | ||||||
| #include <LibCore/Object.h> | #include <LibCore/Object.h> | ||||||
| #include <LibCore/Promise.h> | #include <LibCore/Promise.h> | ||||||
| #include <LibCore/ThreadEventQueue.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); |         Threading::MutexLocker lock(m_private->mutex); | ||||||
|         m_private->queued_events.empend(receiver, move(event)); |         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) | void ThreadEventQueue::add_job(NonnullRefPtr<Promise<NonnullRefPtr<Object>>> promise) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling