[libcamera-devel,v2,1/8] cam: event_loop: Add support for file descriptor events
diff mbox series

Message ID 20210730010306.19956-2-laurent.pinchart@ideasonboard.com
State Accepted
Headers show
Series
  • libcamera: Add DRM/KMS viewfinder display to cam
Related show

Commit Message

Laurent Pinchart July 30, 2021, 1:02 a.m. UTC
Extend the EventLoop class to support watching file descriptors for
read and write events.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/cam/event_loop.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++
 src/cam/event_loop.h   | 20 +++++++++++++++++++
 2 files changed, 64 insertions(+)

Comments

Niklas Söderlund July 31, 2021, 10:51 p.m. UTC | #1
Hi Laurent,

Thanks for your work.

On 2021-07-30 04:02:59 +0300, Laurent Pinchart wrote:
> Extend the EventLoop class to support watching file descriptors for
> read and write events.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>

> ---
>  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
>
Paul Elder Aug. 3, 2021, 6:43 a.m. UTC | #2
Hi Laurent,

On Fri, Jul 30, 2021 at 04:02:59AM +0300, Laurent Pinchart wrote:
> Extend the EventLoop class to support watching file descriptors for
> read and write events.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Paul Elder <paul.elder@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
>
Kieran Bingham Aug. 3, 2021, 10:35 a.m. UTC | #3
Hi Laurent,

On 30/07/2021 02:02, Laurent Pinchart wrote:
> Extend the EventLoop class to support watching file descriptors for
> read and write events.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@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,
>
Laurent Pinchart Aug. 3, 2021, 10:43 a.m. UTC | #4
Hi Kieran,

On Tue, Aug 03, 2021 at 11:35:34AM +0100, Kieran Bingham wrote:
> Hi Laurent,

Yes ? :-)

> On 30/07/2021 02:02, Laurent Pinchart wrote:
> > Extend the EventLoop class to support watching file descriptors for
> > read and write events.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@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,
> >
Kieran Bingham Aug. 3, 2021, 10:44 a.m. UTC | #5
On 03/08/2021 11:43, Laurent Pinchart wrote:
> Hi Kieran,
> 
> On Tue, Aug 03, 2021 at 11:35:34AM +0100, Kieran Bingham wrote:
>> Hi Laurent,
> 
> Yes ? :-)

Agreed. ... ;-)


> 
>> On 30/07/2021 02:02, Laurent Pinchart wrote:
>>> Extend the EventLoop class to support watching file descriptors for
>>> read and write events.
>>>
>>> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Reviewed-by: Kieran Bingham <kieran.bingham@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,
>>>
>
Umang Jain Aug. 4, 2021, 5:32 a.m. UTC | #6
Hi Laurent,

On 7/30/21 6:32 AM, Laurent Pinchart wrote:
> Extend the EventLoop class to support watching file descriptors for
> read and write events.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@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,

Patch
diff mbox series

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,