From b5681992e1caebeac2d95d84690e06dd99234439 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 5 Oct 2022 20:09:55 +0200 Subject: [PATCH] LibIPC: Allow overriding the use of deferred_invoke() This will allow Ladybird to use IPC::Connection without having an actively running Core::EventLoop. The abstraction here is not great, and we should think of something nicer, but we have to start somewhere. --- Userland/Libraries/LibIPC/Connection.cpp | 23 ++++++++++++++++++++--- Userland/Libraries/LibIPC/Connection.h | 16 +++++++++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibIPC/Connection.cpp b/Userland/Libraries/LibIPC/Connection.cpp index f29ea1ecbde..465afd93de7 100644 --- a/Userland/Libraries/LibIPC/Connection.cpp +++ b/Userland/Libraries/LibIPC/Connection.cpp @@ -12,14 +12,29 @@ namespace IPC { +struct CoreEventLoopDeferredInvoker final : public DeferredInvoker { + virtual ~CoreEventLoopDeferredInvoker() = default; + + virtual void schedule(Function callback) override + { + Core::deferred_invoke(move(callback)); + } +}; + ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr socket, u32 local_endpoint_magic) : m_local_stub(local_stub) , m_socket(move(socket)) , m_local_endpoint_magic(local_endpoint_magic) + , m_deferred_invoker(make()) { m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); }); } +void ConnectionBase::set_deferred_invoker(NonnullOwnPtr deferred_invoker) +{ + m_deferred_invoker = move(deferred_invoker); +} + void ConnectionBase::set_fd_passing_socket(NonnullOwnPtr socket) { m_fd_passing_socket = move(socket); @@ -157,7 +172,9 @@ ErrorOr> ConnectionBase::read_as_much_as_possible_from_socket_without auto bytes_read = maybe_bytes_read.release_value(); if (bytes_read.is_empty()) { - deferred_invoke([this] { shutdown(); }); + m_deferred_invoker->schedule([strong_this = NonnullRefPtr(*this)]() mutable { + strong_this->shutdown(); + }); if (!bytes.is_empty()) break; return Error::from_string_literal("IPC connection EOF"); @@ -194,8 +211,8 @@ ErrorOr ConnectionBase::drain_messages_from_peer() } if (!m_unprocessed_messages.is_empty()) { - deferred_invoke([this] { - handle_messages(); + m_deferred_invoker->schedule([strong_this = NonnullRefPtr(*this)]() mutable { + strong_this->handle_messages(); }); } return {}; diff --git a/Userland/Libraries/LibIPC/Connection.h b/Userland/Libraries/LibIPC/Connection.h index e2a41c0dc62..67e66139bd4 100644 --- a/Userland/Libraries/LibIPC/Connection.h +++ b/Userland/Libraries/LibIPC/Connection.h @@ -27,6 +27,13 @@ namespace IPC { +// NOTE: This is an abstraction to allow using IPC::Connection without a Core::EventLoop. +// FIXME: It's not particularly nice, think of something nicer. +struct DeferredInvoker { + virtual ~DeferredInvoker() = default; + virtual void schedule(Function) = 0; +}; + class ConnectionBase : public Core::Object { C_OBJECT_ABSTRACT(ConnectionBase); @@ -34,6 +41,7 @@ public: virtual ~ConnectionBase() override = default; void set_fd_passing_socket(NonnullOwnPtr); + void set_deferred_invoker(NonnullOwnPtr); bool is_open() const { return m_socket->is_open(); } ErrorOr post_message(Message const&); @@ -41,12 +49,12 @@ public: void shutdown(); virtual void die() { } -protected: - explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr, u32 local_endpoint_magic); - Core::Stream::LocalSocket& socket() { return *m_socket; } Core::Stream::LocalSocket& fd_passing_socket(); +protected: + explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr, u32 local_endpoint_magic); + virtual void may_have_become_unresponsive() { } virtual void did_become_responsive() { } virtual void try_parse_messages(Vector const& bytes, size_t& index) = 0; @@ -71,6 +79,8 @@ protected: ByteBuffer m_unprocessed_bytes; u32 m_local_endpoint_magic { 0 }; + + NonnullOwnPtr m_deferred_invoker; }; template