llmx-rtaco 0.0.1
RTNL-only netlink control-plane library for Linux (C++23).
Loading...
Searching...
No Matches
nl_signal.hxx
Go to the documentation of this file.
1#pragma once
2
3#include <functional>
4#include <future>
5#include <memory>
6#include <tuple>
7#include <type_traits>
8#include <utility>
9#include <vector>
10
11#include <boost/asio/any_io_executor.hpp>
12#include <boost/asio/awaitable.hpp>
13#include <boost/asio/co_spawn.hpp>
14#include <boost/asio/post.hpp>
15#include <boost/asio/use_awaitable.hpp>
16#include <boost/asio/use_future.hpp>
17#include <boost/signals2/connection.hpp>
18#include <boost/signals2/signal.hpp>
19
20namespace llmx {
21namespace rtaco {
22
23enum class ExecPolicy {
26};
27
28namespace detail {
29
30template<typename T>
31auto make_ready_shared_future(T&& value) -> std::shared_future<std::decay_t<T>> {
32 std::promise<std::decay_t<T>> promise{};
33 promise.set_value(std::forward<T>(value));
34 return promise.get_future().share();
35}
36
37inline auto make_ready_shared_future() -> std::shared_future<void> {
38 std::promise<void> promise{};
39 promise.set_value();
40 return promise.get_future().share();
41}
42
43template<typename R>
45 using result_type = std::vector<R>;
46
47 template<typename InputIterator>
48 auto operator()(InputIterator first, InputIterator last) const -> result_type {
49 result_type results{};
50 for (; first != last; ++first) {
51 results.push_back((*first).get());
52 }
53 return results;
54 }
55};
56
57template<>
58struct WaitAllCombiner<void> {
59 using result_type = void;
60
61 template<typename InputIterator>
62 void operator()(InputIterator first, InputIterator last) const {
63 for (; first != last; ++first) {
64 (*first).get();
65 }
66 }
67};
68
69template<typename Signature>
71
72template<typename R, typename... Args>
73struct SignalTraits<R(Args...)> {
74 using result_t = R;
75 using args_tuple = std::tuple<Args...>;
77};
78
79} // namespace detail
80
88template<typename Signature,
89 typename Combiner = typename detail::SignalTraits<Signature>::default_combiner>
90class Signal;
91
92template<typename R, typename... Args, typename Combiner>
93class Signal<R(Args...), Combiner> {
94public:
95 using slot_t = std::function<R(Args...)>;
96 using future_t = std::shared_future<R>;
97 using signal_t = boost::signals2::signal<future_t(Args...), Combiner>;
98 using connection_t = boost::signals2::connection;
99 using result_t = typename signal_t::result_type;
100
102 explicit Signal(boost::asio::any_io_executor executor)
103 : executor_{executor} {}
104
111 template<typename Slot>
112 auto connect(Slot&& slot, ExecPolicy policy = ExecPolicy::Sync) -> connection_t {
113 auto slot_fn = slot_t{std::forward<Slot>(slot)};
114
115 return signal_
116 .connect([slot_fn = std::move(slot_fn), policy, executor = executor_](
117 Args... args) mutable -> future_t
118 {
119 auto args_pack = std::make_shared<std::tuple<std::decay_t<Args>...>>(
120 std::forward<Args>(args)...);
121
122 if (policy == ExecPolicy::Sync) {
123 if constexpr (std::is_void_v<R>) {
124 std::apply(slot_fn, *args_pack);
125 return detail::make_ready_shared_future();
126 } else {
127 return detail::make_ready_shared_future(
128 std::apply(slot_fn, *args_pack));
129 }
130 }
131
132 if constexpr (std::is_void_v<R>) {
133 auto coroutine =
134 [slot_fn, args_pack,
135 executor]() mutable -> boost::asio::awaitable<void>
136 {
137 co_await boost::asio::post(executor, boost::asio::use_awaitable);
138 std::apply(slot_fn, *args_pack);
139 };
140
141 auto future = boost::asio::co_spawn(executor, std::move(coroutine),
142 boost::asio::use_future);
143 return future.share();
144 }
145
146 auto coroutine = [slot_fn, args_pack,
147 executor]() mutable -> boost::asio::awaitable<R>
148 {
149 co_await boost::asio::post(executor, boost::asio::use_awaitable);
150 co_return std::apply(slot_fn, *args_pack);
151 };
152
153 auto future = boost::asio::co_spawn(executor, std::move(coroutine),
154 boost::asio::use_future);
155 return future.share();
156 });
157 }
158
160 auto emit(Args... args) -> result_t {
161 return signal_(std::forward<Args>(args)...);
162 }
163
165 auto operator()(Args... args) -> result_t {
166 return emit(std::forward<Args>(args)...);
167 }
168
169private:
170 boost::asio::any_io_executor executor_;
172};
173
174} // namespace rtaco
175} // namespace llmx
boost::asio::any_io_executor executor_
Definition nl_signal.hxx:170
signal_t signal_
Definition nl_signal.hxx:171
std::shared_future< R > future_t
Definition nl_signal.hxx:96
auto emit(Args... args) -> result_t
Emit the signal and run all connected slots.
Definition nl_signal.hxx:160
boost::signals2::connection connection_t
Definition nl_signal.hxx:98
auto operator()(Args... args) -> result_t
Shortcut to emit the signal.
Definition nl_signal.hxx:165
boost::signals2::signal< future_t(Args...), Combiner > signal_t
Definition nl_signal.hxx:97
typename signal_t::result_type result_t
Definition nl_signal.hxx:99
std::function< R(Args...)> slot_t
Definition nl_signal.hxx:95
Signal(boost::asio::any_io_executor executor)
Construct a Signal that will execute slots on the given executor.
Definition nl_signal.hxx:102
auto connect(Slot &&slot, ExecPolicy policy=ExecPolicy::Sync) -> connection_t
Connect a slot to the signal.
Definition nl_signal.hxx:112
Signal/slot wrapper supporting synchronous and asynchronous execution.
Definition nl_signal.hxx:90
Definition nl_signal.hxx:28
auto make_ready_shared_future(T &&value) -> std::shared_future< std::decay_t< T > >
Definition nl_signal.hxx:31
Definition nl_common.hxx:22
ExecPolicy
Definition nl_signal.hxx:23
@ Async
Definition nl_signal.hxx:25
@ Sync
Definition nl_signal.hxx:24
Definition nl_common.hxx:21
WaitAllCombiner< R > default_combiner
Definition nl_signal.hxx:76
std::tuple< Args... > args_tuple
Definition nl_signal.hxx:75
Definition nl_signal.hxx:70
void result_type
Definition nl_signal.hxx:59
void operator()(InputIterator first, InputIterator last) const
Definition nl_signal.hxx:62
Definition nl_signal.hxx:44
auto operator()(InputIterator first, InputIterator last) const -> result_type
Definition nl_signal.hxx:48
std::vector< R > result_type
Definition nl_signal.hxx:45