Aria 2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Loading...
Searching...
No Matches
safe_run.hpp
Go to the documentation of this file.
1#pragma once
2
3// Helpers that hide the C++20/C++23 "no co_await in catch" rule and the
4// "must hop back to UI thread before mutating" rule.
5//
6// on_ui(ui_exec, []() -> Task<R> { ... }); // run, end on UI thread
7// on_ui_safe(ui, body, on_error); // also routes errors
8//
9// Inside the lambda you can `co_await` freely; if you throw, the error
10// handler is called on the UI thread (or rethrown if no handler).
11
13#include "aria/async/task.hpp"
14
15#include <exception>
16#include <functional>
17#include <optional>
18#include <stdexcept>
19#include <type_traits>
20#include <utility>
21
22namespace aria::async {
23
24namespace detail {
25
26template<typename Fn>
27using body_result_t = typename std::invoke_result_t<Fn>::promise_type::value_type;
28
29} // namespace detail
30
33template<typename Fn>
34auto on_ui(IExecutor& ui_exec, Fn body) -> Task<detail::body_result_t<Fn>> {
35 using R = detail::body_result_t<Fn>;
36 std::exception_ptr ex;
37
38 if constexpr (std::is_void_v<R>) {
39 try { co_await body(); } catch (...) { ex = std::current_exception(); }
40 co_await schedule_on(ui_exec);
41 if (ex) std::rethrow_exception(ex);
42 } else {
43 std::optional<R> result;
44 try { result.emplace(co_await body()); } catch (...) { ex = std::current_exception(); }
45 co_await schedule_on(ui_exec);
46 if (ex) std::rethrow_exception(ex);
47 co_return std::move(*result);
48 }
49}
50
54template<typename Body, typename OnError>
55Task<void> on_ui_safe(IExecutor& ui_exec, Body body, OnError on_error) {
56 std::exception_ptr ex;
57 try {
58 co_await body();
59 } catch (...) {
60 ex = std::current_exception();
61 }
62 co_await schedule_on(ui_exec);
63 if (ex) {
64 try { std::rethrow_exception(ex); }
65 catch (const std::exception& e) { on_error(e); }
66 catch (...) {
67 std::runtime_error generic("unknown exception");
68 on_error(generic);
69 }
70 }
71}
72
73} // namespace aria::async
Abstract executor interface — schedules a callable to run "somewhere".
Definition executor.hpp:36
Definition task.hpp:78
Definition async_command.hpp:118
auto schedule_on(IExecutor &exec)
Schedule a coroutine to resume on the given executor.
Definition executor.hpp:396
Task< void > on_ui_safe(IExecutor &ui_exec, Body body, OnError on_error)
Like on_ui(), but routes any exception to on_error(e) on the UI thread.
Definition safe_run.hpp:55
auto on_ui(IExecutor &ui_exec, Fn body) -> Task< detail::body_result_t< Fn > >
Run body() (a coroutine factory).
Definition safe_run.hpp:34