From patchwork Wed Aug 4 12:43:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13196 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 1D60CC3235 for ; Wed, 4 Aug 2021 12:43:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A944A6888D; Wed, 4 Aug 2021 14:43:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="AheqcOWW"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 471C46880F for ; Wed, 4 Aug 2021 14:43:30 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D64C6891 for ; Wed, 4 Aug 2021 14:43:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1628081010; bh=snoZbTLRJ3Q4XSYBQAHNFepvcP99fkqBjgz1hEsawvc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=AheqcOWWQobBrimePvej2MYd5gcR6t43aEWSZRSMGhk0kHibZtyBAW9bBlZvZ54yF 1KWHG6jpkO1kwqR7m8BPvahaZOeZH3QQ5iKSPdFsb6E6IX/X4BlG0QfLjpq/u7FUUJ 3UXO3IyrK2DfkEkff56RP10/4A8XauM8Y1sJorL4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Wed, 4 Aug 2021 15:43:07 +0300 Message-Id: <20210804124314.8044-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210804124314.8044-1-laurent.pinchart@ideasonboard.com> References: <20210804124314.8044-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v3 1/8] cam: event_loop: Add support for file descriptor events X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend the EventLoop class to support watching file descriptors for read and write events. Signed-off-by: Laurent Pinchart Reviewed-by: Niklas Söderlund Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham Reviewed-by: Umang Jain --- src/cam/event_loop.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++ src/cam/event_loop.h | 20 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/cam/event_loop.cpp b/src/cam/event_loop.cpp index 6a4c47f287d0..e25784c083cf 100644 --- a/src/cam/event_loop.cpp +++ b/src/cam/event_loop.cpp @@ -10,6 +10,7 @@ #include #include #include +#include EventLoop *EventLoop::instance_ = nullptr; @@ -26,6 +27,7 @@ EventLoop::~EventLoop() { instance_ = nullptr; + events_.clear(); event_base_free(base_); libevent_global_shutdown(); } @@ -58,6 +60,30 @@ void EventLoop::callLater(const std::function &func) event_base_once(base_, -1, EV_TIMEOUT, dispatchCallback, this, nullptr); } +void EventLoop::addEvent(int fd, EventType type, + const std::function &callback) +{ + std::unique_ptr event = std::make_unique(callback); + short events = (type & Read ? EV_READ : 0) + | (type & Write ? EV_WRITE : 0) + | EV_PERSIST; + + event->event_ = event_new(base_, fd, events, &EventLoop::Event::dispatch, + event.get()); + if (!event->event_) { + std::cerr << "Failed to create event for fd " << fd << std::endl; + return; + } + + int ret = event_add(event->event_, nullptr); + if (ret < 0) { + std::cerr << "Failed to add event for fd " << fd << std::endl; + return; + } + + events_.push_back(std::move(event)); +} + void EventLoop::dispatchCallback([[maybe_unused]] evutil_socket_t fd, [[maybe_unused]] short flags, void *param) { @@ -80,3 +106,21 @@ void EventLoop::dispatchCall() call(); } + +EventLoop::Event::Event(const std::function &callback) + : callback_(callback), event_(nullptr) +{ +} + +EventLoop::Event::~Event() +{ + event_del(event_); + event_free(event_); +} + +void EventLoop::Event::dispatch([[maybe_unused]] int fd, + [[maybe_unused]] short events, void *arg) +{ + Event *event = static_cast(arg); + event->callback_(); +} diff --git a/src/cam/event_loop.h b/src/cam/event_loop.h index ba3ba3a4a675..57bb6fb34aa7 100644 --- a/src/cam/event_loop.h +++ b/src/cam/event_loop.h @@ -8,6 +8,7 @@ #define __CAM_EVENT_LOOP_H__ #include +#include #include #include @@ -18,6 +19,11 @@ struct event_base; class EventLoop { public: + enum EventType { + Read = 1, + Write = 2, + }; + EventLoop(); ~EventLoop(); @@ -28,13 +34,27 @@ public: void callLater(const std::function &func); + void addEvent(int fd, EventType type, + const std::function &handler); + private: + struct Event { + Event(const std::function &callback); + ~Event(); + + static void dispatch(int fd, short events, void *arg); + + std::function callback_; + struct event *event_; + }; + static EventLoop *instance_; struct event_base *base_; int exitCode_; std::list> calls_; + std::list> events_; std::mutex lock_; static void dispatchCallback(evutil_socket_t fd, short flags,