/// @file dpf/net/stream_edge_mesh.hpp /// @brief Multi-edge `stream_array_sink` trio (peer / rss_next / dealer). #ifndef LIBDPF_INCLUDE_DPF_NET_STREAM_EDGE_MESH_HPP__ #define LIBDPF_INCLUDE_DPF_NET_STREAM_EDGE_MESH_HPP__ #include #include #include #include #include "dpf/net/edge_mesh.hpp" #include "dpf/net/stream_array.hpp" #include "dpf/net/stream_mesh.hpp" namespace dpf { namespace net { /// @brief Owns up to three multi-round sinks bound to stream arrays. struct stream_edge_sinks { std::unique_ptr peer; std::unique_ptr rss_next; std::unique_ptr dealer; edge_mesh mesh() const { edge_mesh m; m.sinks = {peer.get(), rss_next.get(), dealer.get()}; return m; } }; /// @brief Build sinks from optional stream arrays and per-channel slot widths. /// @details Null arrays or empty slot lists leave that edge unbound. inline stream_edge_sinks make_stream_edge_sinks(stream_array * peer, std::vector peer_slots, stream_array * rss, std::vector rss_slots, stream_array * dealer, std::vector dealer_slots, std::size_t lanes = 1) { stream_edge_sinks out; if (peer != nullptr && !peer_slots.empty()) out.peer = std::make_unique(*peer, std::move(peer_slots), lanes); if (rss != nullptr && !rss_slots.empty()) out.rss_next = std::make_unique(*rss, std::move(rss_slots), lanes); if (dealer != nullptr && !dealer_slots.empty()) out.dealer = std::make_unique(*dealer, std::move(dealer_slots), lanes); return out; } /// @brief RSS ring edge `(me → (me+1)%3)` on a 3-party stream clique. inline stream_array & rss_next_ring_edge(memory_stream_clique & clique, unsigned me) { if (clique.parties != 3) throw std::invalid_argument("rss_next_ring_edge: need 3 parties"); if (me > 2) throw std::invalid_argument("rss_next_ring_edge party"); const unsigned next = static_cast((me + 1) % 3); return clique.end(me, next); } } // namespace net } // namespace dpf #endif