mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:17:44 +00:00
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.
This commit is contained in:
parent
f877782117
commit
b5681992e1
2 changed files with 33 additions and 6 deletions
|
@ -12,14 +12,29 @@
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
|
struct CoreEventLoopDeferredInvoker final : public DeferredInvoker {
|
||||||
|
virtual ~CoreEventLoopDeferredInvoker() = default;
|
||||||
|
|
||||||
|
virtual void schedule(Function<void()> callback) override
|
||||||
|
{
|
||||||
|
Core::deferred_invoke(move(callback));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::Stream::LocalSocket> socket, u32 local_endpoint_magic)
|
ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::Stream::LocalSocket> socket, u32 local_endpoint_magic)
|
||||||
: m_local_stub(local_stub)
|
: m_local_stub(local_stub)
|
||||||
, m_socket(move(socket))
|
, m_socket(move(socket))
|
||||||
, m_local_endpoint_magic(local_endpoint_magic)
|
, m_local_endpoint_magic(local_endpoint_magic)
|
||||||
|
, m_deferred_invoker(make<CoreEventLoopDeferredInvoker>())
|
||||||
{
|
{
|
||||||
m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); });
|
m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnectionBase::set_deferred_invoker(NonnullOwnPtr<DeferredInvoker> deferred_invoker)
|
||||||
|
{
|
||||||
|
m_deferred_invoker = move(deferred_invoker);
|
||||||
|
}
|
||||||
|
|
||||||
void ConnectionBase::set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket> socket)
|
void ConnectionBase::set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket> socket)
|
||||||
{
|
{
|
||||||
m_fd_passing_socket = move(socket);
|
m_fd_passing_socket = move(socket);
|
||||||
|
@ -157,7 +172,9 @@ ErrorOr<Vector<u8>> ConnectionBase::read_as_much_as_possible_from_socket_without
|
||||||
|
|
||||||
auto bytes_read = maybe_bytes_read.release_value();
|
auto bytes_read = maybe_bytes_read.release_value();
|
||||||
if (bytes_read.is_empty()) {
|
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())
|
if (!bytes.is_empty())
|
||||||
break;
|
break;
|
||||||
return Error::from_string_literal("IPC connection EOF");
|
return Error::from_string_literal("IPC connection EOF");
|
||||||
|
@ -194,8 +211,8 @@ ErrorOr<void> ConnectionBase::drain_messages_from_peer()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_unprocessed_messages.is_empty()) {
|
if (!m_unprocessed_messages.is_empty()) {
|
||||||
deferred_invoke([this] {
|
m_deferred_invoker->schedule([strong_this = NonnullRefPtr(*this)]() mutable {
|
||||||
handle_messages();
|
strong_this->handle_messages();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -27,6 +27,13 @@
|
||||||
|
|
||||||
namespace IPC {
|
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<void()>) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class ConnectionBase : public Core::Object {
|
class ConnectionBase : public Core::Object {
|
||||||
C_OBJECT_ABSTRACT(ConnectionBase);
|
C_OBJECT_ABSTRACT(ConnectionBase);
|
||||||
|
|
||||||
|
@ -34,6 +41,7 @@ public:
|
||||||
virtual ~ConnectionBase() override = default;
|
virtual ~ConnectionBase() override = default;
|
||||||
|
|
||||||
void set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket>);
|
void set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket>);
|
||||||
|
void set_deferred_invoker(NonnullOwnPtr<DeferredInvoker>);
|
||||||
|
|
||||||
bool is_open() const { return m_socket->is_open(); }
|
bool is_open() const { return m_socket->is_open(); }
|
||||||
ErrorOr<void> post_message(Message const&);
|
ErrorOr<void> post_message(Message const&);
|
||||||
|
@ -41,12 +49,12 @@ public:
|
||||||
void shutdown();
|
void shutdown();
|
||||||
virtual void die() { }
|
virtual void die() { }
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::Stream::LocalSocket>, u32 local_endpoint_magic);
|
|
||||||
|
|
||||||
Core::Stream::LocalSocket& socket() { return *m_socket; }
|
Core::Stream::LocalSocket& socket() { return *m_socket; }
|
||||||
Core::Stream::LocalSocket& fd_passing_socket();
|
Core::Stream::LocalSocket& fd_passing_socket();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::Stream::LocalSocket>, u32 local_endpoint_magic);
|
||||||
|
|
||||||
virtual void may_have_become_unresponsive() { }
|
virtual void may_have_become_unresponsive() { }
|
||||||
virtual void did_become_responsive() { }
|
virtual void did_become_responsive() { }
|
||||||
virtual void try_parse_messages(Vector<u8> const& bytes, size_t& index) = 0;
|
virtual void try_parse_messages(Vector<u8> const& bytes, size_t& index) = 0;
|
||||||
|
@ -71,6 +79,8 @@ protected:
|
||||||
ByteBuffer m_unprocessed_bytes;
|
ByteBuffer m_unprocessed_bytes;
|
||||||
|
|
||||||
u32 m_local_endpoint_magic { 0 };
|
u32 m_local_endpoint_magic { 0 };
|
||||||
|
|
||||||
|
NonnullOwnPtr<DeferredInvoker> m_deferred_invoker;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename LocalEndpoint, typename PeerEndpoint>
|
template<typename LocalEndpoint, typename PeerEndpoint>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue