[libcamera-devel] [PATCH v3 1/8] cam: event_loop: Add support for file descriptor events

Laurent Pinchart laurent.pinchart at ideasonboard.com
Wed Aug 4 14:43:07 CEST 2021


Extend the EventLoop class to support watching file descriptors for
read and write events.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Paul Elder <paul.elder at ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain at ideasonboard.com>
---
 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 <assert.h>
 #include <event2/event.h>
 #include <event2/thread.h>
+#include <iostream>
 
 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<void()> &func)
 	event_base_once(base_, -1, EV_TIMEOUT, dispatchCallback, this, nullptr);
 }
 
+void EventLoop::addEvent(int fd, EventType type,
+			 const std::function<void()> &callback)
+{
+	std::unique_ptr<Event> event = std::make_unique<Event>(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<void()> &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<Event *>(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 <functional>
+#include <memory>
 #include <list>
 #include <mutex>
 
@@ -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<void()> &func);
 
+	void addEvent(int fd, EventType type,
+		      const std::function<void()> &handler);
+
 private:
+	struct Event {
+		Event(const std::function<void()> &callback);
+		~Event();
+
+		static void dispatch(int fd, short events, void *arg);
+
+		std::function<void()> callback_;
+		struct event *event_;
+	};
+
 	static EventLoop *instance_;
 
 	struct event_base *base_;
 	int exitCode_;
 
 	std::list<std::function<void()>> calls_;
+	std::list<std::unique_ptr<Event>> events_;
 	std::mutex lock_;
 
 	static void dispatchCallback(evutil_socket_t fd, short flags,
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list