diff options
author | Martin Braun <martin.braun@ettus.com> | 2021-12-17 11:20:10 +0100 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2022-01-10 14:55:25 -0600 |
commit | 4725e97c6d6baa82d414ea89623ca32732d9bea1 (patch) | |
tree | 75a426d8f4cb4f91ba5fc84977e9e013394947d1 /host/lib/include/uhdlib/transport/rx_streamer_impl.hpp | |
parent | d33deb3cae1f231000745dd077d339dcb004e97b (diff) | |
download | uhd-4725e97c6d6baa82d414ea89623ca32732d9bea1.tar.gz uhd-4725e97c6d6baa82d414ea89623ca32732d9bea1.tar.bz2 uhd-4725e97c6d6baa82d414ea89623ca32732d9bea1.zip |
rfnoc: transport: Check if streamers are connected in send() and recv()
This adds a check in send() and recv() whether or not the streamer is
actually connected. If not, an exception is thrown with the message:
[rx_stream] Attempting to call recv() before all channels are connected!
or
[tx_stream] Attempting to call send() before all channels are connected!
The check is a single boolean flag check, but it does add a branch in
our hot code. Since this event is unlikely, and only happens in badly
configured apps, we will get some help from the CPUs branch prediction
to reduce the additional cost of this check.
Diffstat (limited to 'host/lib/include/uhdlib/transport/rx_streamer_impl.hpp')
-rw-r--r-- | host/lib/include/uhdlib/transport/rx_streamer_impl.hpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp b/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp index f776d9373..1b25b308b 100644 --- a/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp +++ b/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp @@ -13,6 +13,7 @@ #include <uhd/types/endianness.hpp> #include <uhd/utils/log.hpp> #include <uhdlib/transport/rx_streamer_zero_copy.hpp> +#include <algorithm> #include <limits> #include <vector> @@ -74,7 +75,9 @@ class rx_streamer_impl : public rx_streamer public: //! Constructor rx_streamer_impl(const size_t num_ports, const uhd::stream_args_t stream_args) - : _zero_copy_streamer(num_ports), _in_buffs(num_ports) + : _zero_copy_streamer(num_ports) + , _in_buffs(num_ports) + , _chans_connected(num_ports, false) { if (stream_args.cpu_format.empty()) { throw uhd::value_error("[rx_stream] Must provide a cpu_format!"); @@ -99,6 +102,11 @@ public: const size_t mtu = xport->get_mtu(); _hdr_len = std::max(_hdr_len, xport->get_chdr_hdr_len()); _zero_copy_streamer.connect_channel(channel, std::move(xport)); + // Note: The previous call also checks if the channel index was valid. + _chans_connected[channel] = true; + _all_chans_connected = std::all_of(_chans_connected.cbegin(), + _chans_connected.cend(), + [](const bool connected) { return connected; }); if (mtu < _mtu) { set_mtu(mtu); @@ -132,6 +140,11 @@ public: const double timeout, const bool one_packet) override { + if (!_all_chans_connected) { + throw uhd::runtime_error("[rx_stream] Attempting to call recv() before all " + "channels are connected!"); + } + if (_error_metadata_cache.check(metadata)) { return 0; } @@ -422,6 +435,13 @@ private: // Fragment (partially read packet) information size_t _fragment_offset_in_samps = 0; rx_metadata_t _last_fragment_metadata; + + // Store a list of channels that are already connected + std::vector<bool> _chans_connected; + + // Flag to store if all channels are connected. This is to speed up the lookup + // of all channels' connected-status. + bool _all_chans_connected = false; }; }} // namespace uhd::transport |