cam: event_loop: Add support for file descriptor events

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>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
This commit is contained in:
Laurent Pinchart 2020-11-13 06:14:49 +02:00
parent 2c18ebb859
commit cb45af8a9e
2 changed files with 64 additions and 0 deletions

View file

@ -10,6 +10,7 @@
#include <assert.h> #include <assert.h>
#include <event2/event.h> #include <event2/event.h>
#include <event2/thread.h> #include <event2/thread.h>
#include <iostream>
EventLoop *EventLoop::instance_ = nullptr; EventLoop *EventLoop::instance_ = nullptr;
@ -26,6 +27,7 @@ EventLoop::~EventLoop()
{ {
instance_ = nullptr; instance_ = nullptr;
events_.clear();
event_base_free(base_); event_base_free(base_);
libevent_global_shutdown(); 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); 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, void EventLoop::dispatchCallback([[maybe_unused]] evutil_socket_t fd,
[[maybe_unused]] short flags, void *param) [[maybe_unused]] short flags, void *param)
{ {
@ -80,3 +106,21 @@ void EventLoop::dispatchCall()
call(); 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_();
}

View file

@ -8,6 +8,7 @@
#define __CAM_EVENT_LOOP_H__ #define __CAM_EVENT_LOOP_H__
#include <functional> #include <functional>
#include <memory>
#include <list> #include <list>
#include <mutex> #include <mutex>
@ -18,6 +19,11 @@ struct event_base;
class EventLoop class EventLoop
{ {
public: public:
enum EventType {
Read = 1,
Write = 2,
};
EventLoop(); EventLoop();
~EventLoop(); ~EventLoop();
@ -28,13 +34,27 @@ public:
void callLater(const std::function<void()> &func); void callLater(const std::function<void()> &func);
void addEvent(int fd, EventType type,
const std::function<void()> &handler);
private: 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_; static EventLoop *instance_;
struct event_base *base_; struct event_base *base_;
int exitCode_; int exitCode_;
std::list<std::function<void()>> calls_; std::list<std::function<void()>> calls_;
std::list<std::unique_ptr<Event>> events_;
std::mutex lock_; std::mutex lock_;
static void dispatchCallback(evutil_socket_t fd, short flags, static void dispatchCallback(evutil_socket_t fd, short flags,