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 <laurent.pinchart@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
11f5c3ad05
commit
a8113fb3a8
30 changed files with 61 additions and 47 deletions
150
src/apps/common/event_loop.cpp
Normal file
150
src/apps/common/event_loop.cpp
Normal file
|
@ -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 <assert.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/thread.h>
|
||||
#include <iostream>
|
||||
|
||||
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<void()> &func)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> 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<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::addTimerEvent(const std::chrono::microseconds period,
|
||||
const std::function<void()> &callback)
|
||||
{
|
||||
std::unique_ptr<Event> event = std::make_unique<Event>(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<EventLoop *>(param);
|
||||
loop->dispatchCall();
|
||||
}
|
||||
|
||||
void EventLoop::dispatchCall()
|
||||
{
|
||||
std::function<void()> call;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> locker(lock_);
|
||||
if (calls_.empty())
|
||||
return;
|
||||
|
||||
call = calls_.front();
|
||||
calls_.pop_front();
|
||||
}
|
||||
|
||||
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_();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue