diff options
author | Umang Jain <email@uajain.com> | 2020-12-04 13:22:23 +0530 |
---|---|---|
committer | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2020-12-04 10:33:05 +0000 |
commit | b79a04afa753d5cfda47faee9bb4fc7b46c78b01 (patch) | |
tree | 3f52d090ddb1fb50a0f4d7e9b6889363753bb294 /event_loop.cpp | |
parent | 14529b6d1c4a6d405b23157eca8a4b0bec632e00 (diff) |
simple-cam: Provide event-loop backed by libevent
libcamera moved its EventDispatcher and Timer API to its internal API,
since providing an event loop to applications should not be the job of
libcamera. Application utility like cam, were ported to use libevent,
hence inspired from that, un-break simple-cam by using the similar
implementation to replace the EventDispatcher and Timer functionality
by libevent.
Signed-off-by: Umang Jain <email@uajain.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'event_loop.cpp')
-rw-r--r-- | event_loop.cpp | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/event_loop.cpp b/event_loop.cpp new file mode 100644 index 0000000..7b6ea65 --- /dev/null +++ b/event_loop.cpp @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020, Google Inc. + * + * event_loop.cpp - Event loop based on cam + */ + +#include "event_loop.h" + +#include <assert.h> +#include <event2/event.h> +#include <event2/thread.h> + +EventLoop *EventLoop::instance_ = nullptr; + +EventLoop::EventLoop() +{ + assert(!instance_); + + evthread_use_pthreads(); + event_ = event_base_new(); + instance_ = this; +} + +EventLoop::~EventLoop() +{ + instance_ = nullptr; + + event_base_free(event_); + libevent_global_shutdown(); +} + +int EventLoop::exec() +{ + exitCode_ = -1; + exit_.store(false, std::memory_order_release); + + while (!exit_.load(std::memory_order_acquire)) { + dispatchCalls(); + event_base_loop(event_, EVLOOP_NO_EXIT_ON_EMPTY); + } + + return exitCode_; +} + +void EventLoop::exit(int code) +{ + exitCode_ = code; + exit_.store(true, std::memory_order_release); + interrupt(); +} + +void EventLoop::interrupt() +{ + event_base_loopbreak(event_); +} + + +void EventLoop::timeoutTriggered(int fd, short event, void *arg) +{ + EventLoop *self = static_cast<EventLoop *>(arg); + self->exit(); +} + +void EventLoop::timeout(unsigned int sec) +{ + struct event *ev; + struct timeval tv; + + tv.tv_sec = sec; + tv.tv_usec = 0; + ev = evtimer_new(event_, &timeoutTriggered, this); + evtimer_add(ev, &tv); +} + +void EventLoop::callLater(const std::function<void()> &func) +{ + { + std::unique_lock<std::mutex> locker(lock_); + calls_.push_back(func); + } + + interrupt(); +} + +void EventLoop::dispatchCalls() +{ + std::unique_lock<std::mutex> locker(lock_); + + for (auto iter = calls_.begin(); iter != calls_.end(); ) { + std::function<void()> call = std::move(*iter); + + iter = calls_.erase(iter); + + locker.unlock(); + call(); + locker.lock(); + } +} |