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