1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2019, Google Inc. * * event-dispatcher.cpp - Event dispatcher test */ #include <chrono> #include <iostream> #include <signal.h> #include <sys/time.h> #include <libcamera/base/event_dispatcher.h> #include <libcamera/base/thread.h> #include <libcamera/base/timer.h> #include "test.h" using namespace libcamera; using namespace std; using namespace std::chrono_literals; static EventDispatcher *dispatcher; static bool interrupt; class EventDispatcherTest : public Test { protected: static void sigAlarmHandler(int) { cout << "SIGALARM received" << endl</* 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_(); }