[RFC PATCH v3 07/21] apps: common: event_loop: Make it possible to exit with exception
Barnabás Pőcze
pobrn at protonmail.com
Thu Jan 30 12:50:36 CET 2025
Instead of taking a single integer in `EventLoop:exit()`, change it
so that an `std::exception_ptr` can also be passed. And in `EventLoop::exec()`
rethrow the stored exception (if any).
Furthermore, catch exceptions from deferred calls, and stop the event
loop with the caught exception.
Signed-off-by: Barnabás Pőcze <pobrn at protonmail.com>
---
src/apps/common/event_loop.cpp | 35 +++++++++++++++++++++++++++++-----
src/apps/common/event_loop.h | 6 ++++--
2 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/src/apps/common/event_loop.cpp b/src/apps/common/event_loop.cpp
index 0d7a4a024..13c2d6057 100644
--- a/src/apps/common/event_loop.cpp
+++ b/src/apps/common/event_loop.cpp
@@ -12,6 +12,7 @@
#include <event2/thread.h>
#include <algorithm>
#include <iostream>
+#include <utility>
EventLoop *EventLoop::instance_ = nullptr;
@@ -38,7 +39,14 @@ EventLoop::EventLoop()
self->calls_.pop_front();
}
- call();
+ try {
+ call();
+ }
+ catch (...) {
+ ::event_active(self->callsTrigger_, 0, 0);
+ self->exit(std::current_exception());
+ break;
+ }
}
}, this);
assert(callsTrigger_);
@@ -63,14 +71,31 @@ EventLoop *EventLoop::instance()
int EventLoop::exec()
{
- exitCode_ = -1;
+ {
+ std::lock_guard locker(lock_);
+ result_ = 0;
+ }
+
event_base_loop(base_, EVLOOP_NO_EXIT_ON_EMPTY);
- return exitCode_;
+
+ auto result = [&] {
+ std::lock_guard locker(lock_);
+ return std::exchange(result_, 0);
+ }();
+
+ if (auto *exc = std::get_if<std::exception_ptr>(&result))
+ std::rethrow_exception(std::move(*exc));
+
+ return std::get<int>(result);
}
-void EventLoop::exit(int code)
+void EventLoop::exit(std::variant<int, std::exception_ptr> result)
{
- exitCode_ = code;
+ {
+ std::lock_guard locker(lock_);
+ result_ = std::move(result);
+ }
+
event_base_loopbreak(base_);
}
diff --git a/src/apps/common/event_loop.h b/src/apps/common/event_loop.h
index 6d7d0497a..380c3483a 100644
--- a/src/apps/common/event_loop.h
+++ b/src/apps/common/event_loop.h
@@ -9,11 +9,13 @@
#include <chrono>
#include <deque>
+#include <exception>
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <optional>
+#include <variant>
#include <libcamera/base/class.h>
@@ -35,7 +37,7 @@ public:
static EventLoop *instance();
int exec();
- void exit(int code = 0);
+ void exit(std::variant<int, std::exception_ptr> result = 0);
void callLater(std::function<void()> &&func, std::optional<std::uintptr_t> cookie = {});
void cancelLater(std::optional<std::uintptr_t> cookie = {});
@@ -63,7 +65,7 @@ private:
static EventLoop *instance_;
struct event_base *base_;
- int exitCode_;
+ std::variant<int, std::exception_ptr> result_ = 0;
std::deque<std::pair<std::function<void()>, std::optional<std::uintptr_t>>> calls_;
::event *callsTrigger_ = nullptr;
--
2.48.1
More information about the libcamera-devel
mailing list