mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 19:47:42 +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