Aria
2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Toggle main menu visibility
Loading...
Searching...
No Matches
callback_boundary.hpp
Go to the documentation of this file.
1
#pragma once
2
3
// aria::CallbackBoundary — the single, framework-wide reporting channel for
4
// exceptions that escape a synchronous user callback at a boundary the
5
// framework MUST keep moving past.
6
//
7
// Why this exists
8
// ---------------
9
// Several locations inside the framework run user code in contexts where an
10
// exception cannot be propagated to a meaningful caller:
11
//
12
// * worker threads inside a thread-pool executor;
13
// * the main-thread executor / dispatcher's drain / pump loops;
14
// * the ABI slot trampoline that backs `abi::SignalErased::emit`;
15
// * the virtual-time executor's pump (test-side scheduler);
16
// * detached coroutines (already routed through `aria::async`).
17
//
18
// Historically each site ended in a bare `catch (...) { /* swallow */ }`,
19
// which made production failures invisible. This header defines a single
20
// reporting primitive that those sites all funnel into:
21
//
22
// aria::report_callback_failure("executor.thread_pool.worker",
23
// std::current_exception());
24
//
25
// The host application installs ONE sink with `set_callback_failure_sink`
26
// (typically routed into the logger). Until then the default sink prints a
27
// single line to `stderr` so production failures are never invisible.
28
//
29
// Lifetime / threading
30
// --------------------
31
// * The sink is a function-pointer-based registration stored in an atomic
32
// variable. Installation, replacement, and read use atomic operations.
33
// * The reporter is `noexcept`: a sink that throws is itself caught and
34
// degraded to a `stderr` fallback so the framework's noexcept boundaries
35
// stay honest.
36
// * `std::current_exception()` is captured at the boundary, so each report
37
// carries a structured exception_ptr the sink can rethrow if it wants
38
// typed inspection — ABI / type-erased payloads are not required.
39
//
40
// Layering
41
// --------
42
// This lives in `core` because both `async` (`async_error_sink`) and the
43
// concrete dispatcher / executor implementations need it. `runtime` injects
44
// a default sink that routes into `aria::Logger`. Adapters and binding
45
// layers may, but need not, install their own sinks.
46
47
#include "
aria/abi/export.hpp
"
48
#include "
aria/function_ref.hpp
"
49
50
#include <atomic>
51
#include <cstdio>
52
#include <exception>
53
#include <string>
54
#include <string_view>
55
#include <utility>
56
57
namespace
aria
{
58
66
struct
CallbackFailure
{
67
std::string_view
category
;
68
std::exception_ptr
exception
;
69
std::string_view
message
;
70
};
71
78
using
CallbackFailureSink
= void (*)(
const
CallbackFailure
&);
79
80
namespace
detail::callback_boundary {
81
82
// Shared builds store this slot in libaria_abi. Static builds link one
83
// copy into the host executable; independently linked plugins should use the
84
// shared build if they need process-wide diagnostic registration.
85
ARIA_ABI_API
std::atomic<CallbackFailureSink>& sink_storage()
noexcept
;
86
87
inline
std::string render_message_(
const
CallbackFailure
& f) {
88
if
(!f.
message
.empty())
return
std::string{f.
message
};
89
if
(f.
exception
) {
90
try
{
91
std::rethrow_exception(f.
exception
);
92
}
catch
(
const
std::exception& e) {
93
return
std::string{e.what()};
94
}
catch
(...) {
95
return
"non-std::exception"
;
96
}
97
}
98
return
"(no payload)"
;
99
}
100
101
inline
void
default_sink_(
const
CallbackFailure
& f)
noexcept
{
102
// Fallback: a single, parseable line on stderr. Host apps that want
103
// structured logging install their own sink during runtime startup.
104
try
{
105
const
std::string msg = render_message_(f);
106
std::fprintf(stderr,
"[aria.callback_failure] %.*s: %s\n"
,
107
static_cast<
int
>
(f.
category
.size()), f.
category
.data(),
108
msg.c_str());
109
std::fflush(stderr);
110
}
catch
(...) {
111
// We are already a noexcept boundary of last resort. Even formatting
112
// can fail under OOM; in that case we simply give up — the framework
113
// contract is to never raise from a noexcept boundary.
114
}
115
}
116
117
}
// namespace detail::callback_boundary
118
121
inline
CallbackFailureSink
set_callback_failure_sink
(
CallbackFailureSink
sink)
noexcept
{
122
return
detail::callback_boundary::sink_storage().exchange(sink, std::memory_order_acq_rel);
123
}
124
127
[[nodiscard]]
inline
CallbackFailureSink
current_callback_failure_sink
() noexcept {
128
return
detail::callback_boundary::sink_storage().load(std::memory_order_acquire);
129
}
130
137
ARIA_ABI_API
void
report_callback_failure
(std::string_view category,
138
std::exception_ptr exception,
139
std::string_view message = {})
noexcept
;
140
144
inline
void
report_callback_failure
(std::string_view category,
145
std::string_view message)
noexcept
{
146
report_callback_failure
(category, std::exception_ptr{}, message);
147
}
148
149
}
// namespace aria
export.hpp
ARIA_ABI_API
#define ARIA_ABI_API
Definition
export.hpp:21
function_ref.hpp
aria
Definition
signal.hpp:12
aria::set_callback_failure_sink
CallbackFailureSink set_callback_failure_sink(CallbackFailureSink sink) noexcept
Install a global callback-failure sink.
Definition
callback_boundary.hpp:121
aria::CallbackFailureSink
void(*)(const CallbackFailure &) CallbackFailureSink
Sink type.
Definition
callback_boundary.hpp:78
aria::report_callback_failure
void report_callback_failure(std::string_view category, std::exception_ptr exception, std::string_view message={}) noexcept
Report a callback failure.
aria::current_callback_failure_sink
CallbackFailureSink current_callback_failure_sink() noexcept
Read the currently installed sink.
Definition
callback_boundary.hpp:127
aria::CallbackFailure
Payload passed to a callback-failure sink.
Definition
callback_boundary.hpp:66
aria::CallbackFailure::exception
std::exception_ptr exception
Definition
callback_boundary.hpp:68
aria::CallbackFailure::message
std::string_view message
Definition
callback_boundary.hpp:69
aria::CallbackFailure::category
std::string_view category
Definition
callback_boundary.hpp:67
modules
core
include
aria
callback_boundary.hpp
Generated by
1.18.0