From a8113fb3a89984cc65d51436480cee45b60543e8 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 20 Oct 2022 01:25:45 +0300 Subject: apps: Share common source between applications Multiple source files in the src/apps/cam/ directory are used by cam, qcam and lc-compliance. They are compiled separately for each application. Move them to a new src/apps/common/ directory and compile them in a static library to decrease the number of compilation operations. Signed-off-by: Laurent Pinchart Reviewed-by: Umang Jain Reviewed-by: Kieran Bingham --- src/apps/common/event_loop.cpp | 150 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/apps/common/event_loop.cpp (limited to 'src/apps/common/event_loop.cpp') diff --git a/src/apps/common/event_loop.cpp b/src/apps/common/event_loop.cpp new file mode 100644 index 00000000..cb83845c --- /dev/null +++ b/src/apps/common/event_loop.cpp @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * event_loop.cpp - cam - Event loop + */ + +#include "event_loop.h" + +#include +#include +#include +#include + +EventLoop *EventLoop::instance_ = nullptr; + +EventLoop::EventLoop() +{ + assert(!instance_); + + evthread_use_pthreads(); + base_ = event_base_new(); + instance_ = this; +} + +EventLoop::~EventLoop() +{ + instance_ = nullptr; + + events_.clear(); + event_base_free(base_); + libevent_global_shutdown(); +} + +EventLoop *EventLoop::instance() +{ + return instance_; +} + +int EventLoop::exec() +{ + exitCode_ = -1; + event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY); + return exitCode_; +} + +void EventLoop::exit(int code) +{ + exitCode_ = code; + event_base_loopbreak(base_); +} + +void EventLoop::callLater(const std::function &func) +{ + { + std::unique_lock locker(lock_); + calls_.push_back(func); + } + + event_base_once(base_, -1, EV_TIMEOUT, dispatchCallback, this, nullptr); +} + +void EventLoop::addFdEvent(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::addTimerEvent(const std::chrono::microseconds period, + const std::function &callback) +{ + std::unique_ptr event = std::make_unique(callback); + event->event_ = event_new(base_, -1, EV_PERSIST, &EventLoop::Event::dispatch, + event.get()); + if (!event->event_) { + std::cerr << "Failed to create timer event" << std::endl; + return; + } + + struct timeval tv; + tv.tv_sec = period.count() / 1000000ULL; + tv.tv_usec = period.count() % 1000000ULL; + + int ret = event_add(event->event_, &tv); + if (ret < 0) { + std::cerr << "Failed to add timer event" << std::endl; + return; + } + + events_.push_back(std::move(event)); +} + +void EventLoop::dispatchCallback([[maybe_unused]] evutil_socket_t fd, + [[maybe_unused]] short flags, void *param) +{ + EventLoop *loop = static_cast(param); + loop->dispatchCall(); +} + +void EventLoop::dispatchCall() +{ + std::function call; + + { + std::unique_lock locker(lock_); + if (calls_.empty()) + return; + + call = calls_.front(); + calls_.pop_front(); + } + + 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_(); +} -- cgit v1.2.1