Aria
2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Toggle main menu visibility
Loading...
Searching...
No Matches
event_bus.hpp
Go to the documentation of this file.
1
#pragma once
2
3
#include "
aria/abi/export.hpp
"
4
#include "aria/detail/typed_signal.hpp"
5
#include "
aria/subscription.hpp
"
6
#include "
aria/runtime/dispatcher.hpp
"
7
8
#include <any>
9
#include <atomic>
10
#include <functional>
11
#include <memory>
12
#include <typeindex>
13
14
namespace
aria::runtime
{
15
19
class
ARIA_RUNTIME_API
EventBus
{
20
public
:
21
EventBus
();
22
~EventBus
();
23
24
EventBus
(
const
EventBus
&) =
delete
;
25
EventBus
&
operator=
(
const
EventBus
&) =
delete
;
26
EventBus
(
EventBus
&&) =
delete
;
27
EventBus
&
operator=
(
EventBus
&&) =
delete
;
28
30
static
EventBus
&
global
() noexcept;
31
32
template<typename T>
33
void
publish
(const T& event) {
34
std::shared_ptr<::aria::detail::TypedSignal<T>> sig;
35
auto
found = do_find_signal_(
typeid
(T));
36
if
(!found.has_value())
return
;
37
sig = std::any_cast<std::shared_ptr<::aria::detail::TypedSignal<T>>>(found);
38
sig->emit(event);
39
}
40
41
template
<
typename
T>
42
[[nodiscard]]
::aria::Subscription
subscribe
(std::function<
void
(
const
T&)> handler) {
43
std::shared_ptr<::aria::detail::TypedSignal<T>> sig;
44
auto
found = do_find_signal_(
typeid
(T));
45
if
(found.has_value()) {
46
sig = std::any_cast<std::shared_ptr<::aria::detail::TypedSignal<T>>>(found);
47
}
else
{
48
sig = std::make_shared<::aria::detail::TypedSignal<T>>();
49
auto
existing = do_try_emplace_signal_(
typeid
(T), std::any(sig));
50
if
(existing.has_value()) {
51
sig = std::any_cast<std::shared_ptr<::aria::detail::TypedSignal<T>>>(existing);
52
}
53
}
54
return
sig->connect(std::move(handler));
55
}
56
63
template
<
typename
T>
64
[[nodiscard]]
::aria::Subscription
subscribe_on
(
65
IDispatcher
& dispatcher,
66
std::function<
void
(
const
T&)> handler)
67
{
68
struct
Delivery {
69
std::atomic<bool> active{
true
};
70
std::function<void(
const
T&)> handler;
71
explicit
Delivery(std::function<
void
(
const
T&)> fn) : handler(std::move(fn)) {}
72
};
73
auto
state = std::make_shared<Delivery>(std::move(handler));
74
auto
connection =
subscribe<T>
([&dispatcher, state](
const
T& event) {
75
if
(!state->active.load(std::memory_order_acquire))
return
;
76
auto
keep = std::make_shared<T>(event);
77
dispatcher.
post
([weak = std::weak_ptr{state}, keep = std::move(keep)] {
78
if
(
auto
delivery = weak.lock();
79
delivery && delivery->active.load(std::memory_order_acquire)) {
80
delivery->handler(*keep);
81
}
82
});
83
});
84
try
{
85
return ::aria::Subscription{
86
[weak = std::weak_ptr{state}, connection = std::move(connection)]()
mutable
{
87
if
(
auto
delivery = weak.lock())
88
delivery->active.store(
false
, std::memory_order_release);
89
connection.release();
90
}};
91
}
catch
(...) {
92
state->active.store(
false
, std::memory_order_release);
93
throw
;
94
}
95
}
96
97
void
clear
();
98
99
private
:
100
std::any do_find_signal_(std::type_index ti);
101
std::any do_try_emplace_signal_(std::type_index ti, std::any sig);
102
103
struct
Impl;
104
// RAII pImpl. MSVC would emit C4251 for a std::unique_ptr member of a
105
// dll-exported class (the unique_ptr template is not itself exported),
106
// but the pointee is an *incomplete* opaque type consumed only through
107
// this module's non-template API, so the warning is a false positive —
108
// suppress it locally rather than hand-managing a raw pointer.
109
#ifdef _MSC_VER
110
# pragma warning(push)
111
# pragma warning(disable: 4251)
112
#endif
113
std::unique_ptr<Impl> impl_;
114
#ifdef _MSC_VER
115
# pragma warning(pop)
116
#endif
117
};
118
119
}
// namespace aria::runtime
aria::Subscription
RAII handle to a single subscription.
Definition
subscription.hpp:44
aria::runtime::EventBus::global
static EventBus & global() noexcept
Process-wide global event bus.
aria::runtime::EventBus::operator=
EventBus & operator=(EventBus &&)=delete
aria::runtime::EventBus::EventBus
EventBus(EventBus &&)=delete
aria::runtime::EventBus::publish
void publish(const T &event)
Definition
event_bus.hpp:33
aria::runtime::EventBus::EventBus
EventBus()
aria::runtime::EventBus::operator=
EventBus & operator=(const EventBus &)=delete
aria::runtime::EventBus::~EventBus
~EventBus()
aria::runtime::EventBus::subscribe
::aria::Subscription subscribe(std::function< void(const T &)> handler)
Definition
event_bus.hpp:42
aria::runtime::EventBus::subscribe_on
::aria::Subscription subscribe_on(IDispatcher &dispatcher, std::function< void(const T &)> handler)
Subscribe with a dispatcher — incoming events are marshalled to the dispatcher's thread (e....
Definition
event_bus.hpp:64
aria::runtime::EventBus::clear
void clear()
aria::runtime::EventBus::EventBus
EventBus(const EventBus &)=delete
aria::runtime::IDispatcher
Abstract main-thread dispatcher.
Definition
dispatcher.hpp:26
aria::runtime::IDispatcher::post
virtual void post(std::function< void()> fn)=0
Schedule the callable to run on the main thread (asynchronously).
dispatcher.hpp
export.hpp
ARIA_RUNTIME_API
#define ARIA_RUNTIME_API
Definition
export.hpp:30
aria::runtime
Definition
container.hpp:11
subscription.hpp
modules
runtime
include
aria
runtime
event_bus.hpp
Generated by
1.18.0