From 4dae8b41da0ff30307b88b9925a5b41649c4ed94 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 13 Oct 2021 10:40:48 +0200 Subject: [PATCH] event/PipeEvent: new class wrapping SocketEvent --- src/db/update/InotifySource.cxx | 8 +-- src/db/update/InotifySource.hxx | 4 +- src/event/PipeEvent.hxx | 103 ++++++++++++++++++++++++++++++++ src/event/UringManager.hxx | 6 +- 4 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 src/event/PipeEvent.hxx diff --git a/src/db/update/InotifySource.cxx b/src/db/update/InotifySource.cxx index cdeb18fad..02f0d38f0 100644 --- a/src/db/update/InotifySource.cxx +++ b/src/db/update/InotifySource.cxx @@ -37,7 +37,7 @@ InotifySource::OnSocketReady([[maybe_unused]] unsigned flags) noexcept static_assert(sizeof(buffer) >= sizeof(struct inotify_event) + NAME_MAX + 1, "inotify buffer too small"); - auto ifd = socket_event.GetSocket().ToFileDescriptor(); + auto ifd = socket_event.GetFileDescriptor(); ssize_t nbytes = ifd.Read(buffer, sizeof(buffer)); if (nbytes < 0) FatalSystemError("Failed to read from inotify"); @@ -78,7 +78,7 @@ InotifyInit() InotifySource::InotifySource(EventLoop &_loop, mpd_inotify_callback_t _callback, void *_ctx) :socket_event(_loop, BIND_THIS_METHOD(OnSocketReady), - SocketDescriptor::FromFileDescriptor(InotifyInit())), + InotifyInit()), callback(_callback), callback_ctx(_ctx) { socket_event.ScheduleRead(); @@ -87,7 +87,7 @@ InotifySource::InotifySource(EventLoop &_loop, int InotifySource::Add(const char *path_fs, unsigned mask) { - auto ifd = socket_event.GetSocket().ToFileDescriptor(); + auto ifd = socket_event.GetFileDescriptor(); int wd = inotify_add_watch(ifd.Get(), path_fs, mask); if (wd < 0) throw MakeErrno("inotify_add_watch() has failed"); @@ -98,7 +98,7 @@ InotifySource::Add(const char *path_fs, unsigned mask) void InotifySource::Remove(unsigned wd) noexcept { - auto ifd = socket_event.GetSocket().ToFileDescriptor(); + auto ifd = socket_event.GetFileDescriptor(); int ret = inotify_rm_watch(ifd.Get(), wd); if (ret < 0 && errno != EINVAL) LogErrno(inotify_domain, "inotify_rm_watch() has failed"); diff --git a/src/db/update/InotifySource.hxx b/src/db/update/InotifySource.hxx index 4e626b1aa..7073b5abf 100644 --- a/src/db/update/InotifySource.hxx +++ b/src/db/update/InotifySource.hxx @@ -20,13 +20,13 @@ #ifndef MPD_INOTIFY_SOURCE_HXX #define MPD_INOTIFY_SOURCE_HXX -#include "event/SocketEvent.hxx" +#include "event/PipeEvent.hxx" typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask, const char *name, void *ctx); class InotifySource final { - SocketEvent socket_event; + PipeEvent socket_event; mpd_inotify_callback_t callback; void *callback_ctx; diff --git a/src/event/PipeEvent.hxx b/src/event/PipeEvent.hxx new file mode 100644 index 000000000..dbd9600e3 --- /dev/null +++ b/src/event/PipeEvent.hxx @@ -0,0 +1,103 @@ +/* + * Copyright 2007-2021 CM4all GmbH + * All rights reserved. + * + * author: Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "SocketEvent.hxx" +#include "io/FileDescriptor.hxx" + +/** + * A variant of #SocketEvent for pipes (and other kinds of + * #FileDescriptor which can be used with epoll). + */ +class PipeEvent final { + SocketEvent event; + +public: + template + PipeEvent(EventLoop &event_loop, C callback, + FileDescriptor fd=FileDescriptor::Undefined()) noexcept + :event(event_loop, callback, + SocketDescriptor::FromFileDescriptor(fd)) {} + + EventLoop &GetEventLoop() const noexcept { + return event.GetEventLoop(); + } + + bool IsDefined() const noexcept { + return event.IsDefined(); + } + + FileDescriptor GetFileDescriptor() const noexcept { + return event.GetSocket().ToFileDescriptor(); + } + + FileDescriptor ReleaseFileDescriptor() noexcept { + return event.ReleaseSocket().ToFileDescriptor(); + } + + void Open(FileDescriptor fd) noexcept { + event.Open(SocketDescriptor::FromFileDescriptor(fd)); + } + + void Close() noexcept { + event.Close(); + } + + bool Schedule(unsigned flags) noexcept { + return event.Schedule(flags); + } + + void Cancel() noexcept { + event.Cancel(); + } + + bool ScheduleRead() noexcept { + return event.ScheduleRead(); + } + + bool ScheduleWrite() noexcept { + return event.ScheduleWrite(); + } + + void CancelRead() noexcept { + event.CancelRead(); + } + + void CancelWrite() noexcept { + event.CancelWrite(); + } + + void ScheduleImplicit() noexcept { + event.ScheduleImplicit(); + } +}; diff --git a/src/event/UringManager.hxx b/src/event/UringManager.hxx index 4e0b3442a..43b447d3d 100644 --- a/src/event/UringManager.hxx +++ b/src/event/UringManager.hxx @@ -19,21 +19,21 @@ #pragma once -#include "SocketEvent.hxx" +#include "PipeEvent.hxx" #include "IdleEvent.hxx" #include "io/uring/Queue.hxx" namespace Uring { class Manager final : public Queue { - SocketEvent event; + PipeEvent event; IdleEvent idle_event; public: explicit Manager(EventLoop &event_loop) :Queue(1024, 0), event(event_loop, BIND_THIS_METHOD(OnSocketReady), - SocketDescriptor::FromFileDescriptor(GetFileDescriptor())), + GetFileDescriptor()), idle_event(event_loop, BIND_THIS_METHOD(OnIdle)) { event.ScheduleRead();