11#include "int_arith.hpp"
12#include "introspect.hpp"
13#include "numeric_traits.hpp"
14#include "processor.hpp"
15#include "type_erased_processor.hpp"
16#include "type_list.hpp"
41template <
typename R,
typename... Events>
43 (... &&
requires(R
const &r, Events
const &e) {
44 { r(e) } -> std::same_as<std::size_t>;
55template <
typename Router,
typename EventList>
struct router_for_each_event;
57template <
typename Router,
typename... Events>
58struct router_for_each_event<Router,
type_list<Events...>>
59 : std::bool_constant<router_for<Router, Events...>> {};
62template <
typename RoutedEventList,
typename Router, std::size_t N,
64 requires type_list_like<RoutedEventList> && processor<Downstream> &&
65 router_for_each_event<Router, RoutedEventList>::value
68 std::array<Downstream, N> downstreams;
70 LIBTCSPC_NOINLINE
void flush_all_but(Downstream &excluded) {
71 for (
auto &d : downstreams) {
72 if (&d != &excluded) {
75 }
catch (end_of_processing
const &) {
83 explicit route_homogeneous(Router router,
84 std::array<Downstream, N> downstreams)
85 : router(std::move(router)), downstreams(std::move(downstreams)) {}
87 [[nodiscard]]
auto introspect_node() const -> processor_info {
88 return processor_info(
this,
"route_homogeneous");
91 [[nodiscard]]
auto introspect_graph() const -> processor_graph {
92 return std::transform_reduce(
93 downstreams.begin(), downstreams.end(), processor_graph(),
95 return d.introspect_graph().push_entry_point(
this);
99 template <
typename Event>
100 requires(convertible_to_type_list_member<std::remove_cvref_t<Event>,
102 handler_for<Downstream, std::remove_cvref_t<Event>>)
103 void handle(Event &&event) {
104 std::size_t index = router(std::as_const(event));
108 downstreams[index].handle(std::forward<Event>(event));
109 }
catch (end_of_processing
const &) {
110 flush_all_but(downstreams[index]);
115 template <
typename Event>
116 requires(not convertible_to_type_list_member<
117 std::remove_cvref_t<Event>, RoutedEventList> and
118 handler_for<Downstream, std::remove_cvref_t<Event>>)
119 void handle(Event &&event) {
120 for (
auto &d : downstreams) {
122 d.handle(std::as_const(event));
123 }
catch (end_of_processing
const &) {
131 std::exception_ptr end;
132 for (
auto &d : downstreams) {
135 }
catch (end_of_processing
const &) {
137 end = std::current_exception();
141 std::rethrow_exception(end);
184template <
typename RoutedEventList,
typename Router, std::size_t N,
187 return internal::route_homogeneous<RoutedEventList, Router, N, Downstream>(
188 std::move(router), std::move(downstreams));
227template <
typename RoutedEventList,
typename Router,
typename... Downstreams>
230 std::move(router), std::array{std::move(downstreams)...});
271template <
typename RoutedEventList,
typename BroadcastEventList = type_list<>,
272 typename Router,
typename... Downstreams>
273auto route(Router router, Downstreams... downstreams) {
280 "routed event list and broadcast event list must not overlap");
284 type_erased_downstream>(
286 std::array<type_erased_downstream,
sizeof...(Downstreams)>{
287 type_erased_downstream(std::move(downstreams))...});
303 template <
typename Event>
305 return std::size_t(-1);
318template <std::
size_t N,
typename NumericTraits = default_numeric_traits>
320 std::array<typename NumericTraits::channel_type, N> channels;
321 std::array<std::size_t, N> indices;
333 template <
typename ChannelIndexPair>
335 std::array<ChannelIndexPair, N>
const &channel_indices)
336 : channels(std::invoke([&] {
337 std::array<typename NumericTraits::channel_type, N> ret{};
338 std::transform(channel_indices.begin(), channel_indices.end(),
340 [](
auto p) { return std::get<0>(p); });
343 indices(std::invoke([&] {
344 std::array<std::size_t, N> ret{};
345 std::transform(channel_indices.begin(), channel_indices.end(),
347 [](
auto p) { return std::get<1>(p); });
352 std::is_convertible_v<decltype(std::get<0>(channel_indices[0])),
353 typename NumericTraits::channel_type> &&
354 std::is_convertible_v<
355 decltype(std::get<1>(channel_indices[0])), std::size_t>,
356 "channel_indices must be an array of pair-like convertible to (channel, std::size_t)");
360 template <
typename Event>
362 static_assert(std::is_same_v<
decltype(
event.channel),
363 typename NumericTraits::channel_type>);
364 auto it = std::find(channels.begin(), channels.end(), event.channel);
365 if (it == channels.end())
366 return std::numeric_limits<std::size_t>::max();
367 return indices[internal::as_unsigned(
368 std::distance(channels.begin(), it))];
393template <std::
size_t N,
typename Downstream>
419template <
typename... Downstreams>
421 auto arr = std::array{std::move(downstreams)...};
446template <
typename BroadcastEventList,
typename... Downstreams>
channel_router(std::array< ChannelIndexPair, N > const &channel_indices)
Construct with channels and corresponding downstream indices.
Definition route.hpp:334
auto operator()(Event const &event) const -> std::size_t
Implements router requirement.
Definition route.hpp:361
Router that does not route.
Definition route.hpp:297
auto operator()(Event const &) const -> std::size_t
Implements router requirement; always returns std::numeric_limits<std::size_t>::max().
Definition route.hpp:304
Processor that type-erases the downstream processor.
Definition type_erased_processor.hpp:126
Concept that is satisfied when R conforms to the libtcspc router interface for event types Events.
Definition route.hpp:42
Concept that is satisfied when a type is a tcspc::type_list specialization.
Definition type_list.hpp:64
auto merge_processor_graphs(processor_graph const &a, processor_graph const &b) -> processor_graph
Create a new processor graph by merging two existing ones.
Definition introspect.hpp:380
auto broadcast(Downstreams... downstreams)
Create a processor that broadcasts events to multiple downstream processors.
Definition route.hpp:447
auto route_homogeneous(Router router, std::array< Downstream, N > downstreams)
Create a processor that routes events to multiple downstreams of the same type.
Definition route.hpp:186
auto broadcast_homogeneous(std::array< Downstream, N > downstreams)
Create a processor that broadcasts events to multiple downstream processors of the same type.
Definition route.hpp:394
auto route(Router router, Downstreams... downstreams)
Create a processor that routes events to different downstreams.
Definition route.hpp:273
type_list_intersection< TL0, TL1 >::type type_list_intersection_t
Helper type for tcspc::type_list_intersection.
Definition type_list.hpp:455
constexpr std::size_t type_list_size_v
Helper variable template for tcspc::type_list_size.
Definition type_list.hpp:133
type_list_union< TL0, TL1 >::type type_list_union_t
Helper type for tcspc::type_list_union.
Definition type_list.hpp:399
libtcspc namespace.
Definition acquire.hpp:30
Compile-time representation of a list of types.
Definition type_list.hpp:38