aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/mpmd/mpmd_impl.cpp
diff options
context:
space:
mode:
authorBrent Stapleton <brent.stapleton@ettus.com>2019-01-14 10:35:25 -0800
committerBrent Stapleton <brent.stapleton@ettus.com>2019-01-16 11:40:23 -0800
commit967be2a4e82b1a125b26bb72a60318a4fb2b50c4 (patch)
tree8a24954b54d1546dc8049a17e485adb0a605f74f /host/lib/usrp/mpmd/mpmd_impl.cpp
parentaafe4e8b742a0e21d3818f21f34e3c8613132530 (diff)
downloaduhd-967be2a4e82b1a125b26bb72a60318a4fb2b50c4.tar.gz
uhd-967be2a4e82b1a125b26bb72a60318a4fb2b50c4.tar.bz2
uhd-967be2a4e82b1a125b26bb72a60318a4fb2b50c4.zip
uhd: mpm: apply clang-format to all files
Applying formatting changes to all .cpp and .hpp files in the following directories: ``` find host/examples/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/tests/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/lib/usrp/dboard/neon/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/lib/usrp/dboard/magnesium/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/lib/usrp/device3/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/lib/usrp/mpmd/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/lib/usrp/x300/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find host/utils/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file find mpm/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file ``` Also formatted host/include/, except Cpp03 was used as a the language standard instead of Cpp11. ``` sed -i 's/ Cpp11/ Cpp03/g' .clang-format find host/include/ -iname *.hpp -o -iname *.cpp | \ xargs clang-format -i -style=file ``` Formatting style was designated by the .clang-format file.
Diffstat (limited to 'host/lib/usrp/mpmd/mpmd_impl.cpp')
-rw-r--r--host/lib/usrp/mpmd/mpmd_impl.cpp369
1 files changed, 164 insertions, 205 deletions
diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp
index 87e911e17..b8ce6cabd 100644
--- a/host/lib/usrp/mpmd/mpmd_impl.cpp
+++ b/host/lib/usrp/mpmd/mpmd_impl.cpp
@@ -5,189 +5,166 @@
//
#include "mpmd_impl.hpp"
-#include <../device3/device3_impl.hpp>
#include <uhd/exception.hpp>
-#include <uhd/utils/static.hpp>
-#include <uhd/utils/tasks.hpp>
-#include <uhd/types/sensors.hpp>
-#include <uhd/types/eeprom.hpp>
#include <uhd/types/component_file.hpp>
+#include <uhd/types/eeprom.hpp>
+#include <uhd/types/sensors.hpp>
#include <uhd/usrp/mboard_eeprom.hpp>
-#include <uhdlib/rfnoc/rpc_block_ctrl.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/tasks.hpp>
#include <uhdlib/rfnoc/radio_ctrl_impl.hpp>
+#include <uhdlib/rfnoc/rpc_block_ctrl.hpp>
+#include <../device3/device3_impl.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread.hpp>
+#include <future>
#include <memory>
#include <mutex>
#include <random>
#include <string>
-#include <vector>
-#include <future>
#include <thread>
+#include <vector>
using namespace uhd;
using namespace uhd::mpmd;
namespace {
- /*************************************************************************
- * Local constants
- ************************************************************************/
- const size_t MPMD_CROSSBAR_MAX_LADDR = 255;
- //! Most pessimistic time for a CHDR query to go to device and back
- const double MPMD_CHDR_MAX_RTT = 0.02;
- //! MPM Compatibility number
- const std::vector<size_t> MPM_COMPAT_NUM = {1, 2};
+/*************************************************************************
+ * Local constants
+ ************************************************************************/
+const size_t MPMD_CROSSBAR_MAX_LADDR = 255;
+//! Most pessimistic time for a CHDR query to go to device and back
+const double MPMD_CHDR_MAX_RTT = 0.02;
+//! MPM Compatibility number
+const std::vector<size_t> MPM_COMPAT_NUM = {1, 2};
- /*************************************************************************
- * Helper functions
- ************************************************************************/
- void reset_time_synchronized(uhd::property_tree::sptr tree)
- {
- const size_t n_mboards = tree->list("/mboards").size();
- UHD_LOGGER_DEBUG("MPMD")
- << "Synchronizing " << n_mboards <<" timekeepers...";
- auto get_time_last_pps = [tree](){
- return tree->access<time_spec_t>(
- fs_path("/mboards/0/time/pps")
- ).get();
- };
- auto end_time = std::chrono::steady_clock::now()
- + std::chrono::milliseconds(1100);
- auto time_last_pps = get_time_last_pps();
- UHD_LOG_DEBUG("MPMD", "Waiting for PPS clock edge...");
- while (time_last_pps == get_time_last_pps())
- {
- if (std::chrono::steady_clock::now() > end_time) {
- throw uhd::runtime_error(
- "Board 0 may not be getting a PPS signal!\n"
- "No PPS detected within the time interval.\n"
- "See the application notes for your device.\n"
- );
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- }
- UHD_LOG_DEBUG("MPMD", "Setting all timekeepers to 0...");
- for (size_t mboard_idx = 0; mboard_idx < n_mboards; mboard_idx++) {
- tree->access<time_spec_t>(
- fs_path("/mboards") / mboard_idx / "time" / "pps"
- ).set(time_spec_t(0.0));
+/*************************************************************************
+ * Helper functions
+ ************************************************************************/
+void reset_time_synchronized(uhd::property_tree::sptr tree)
+{
+ const size_t n_mboards = tree->list("/mboards").size();
+ UHD_LOGGER_DEBUG("MPMD") << "Synchronizing " << n_mboards << " timekeepers...";
+ auto get_time_last_pps = [tree]() {
+ return tree->access<time_spec_t>(fs_path("/mboards/0/time/pps")).get();
+ };
+ auto end_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(1100);
+ auto time_last_pps = get_time_last_pps();
+ UHD_LOG_DEBUG("MPMD", "Waiting for PPS clock edge...");
+ while (time_last_pps == get_time_last_pps()) {
+ if (std::chrono::steady_clock::now() > end_time) {
+ throw uhd::runtime_error("Board 0 may not be getting a PPS signal!\n"
+ "No PPS detected within the time interval.\n"
+ "See the application notes for your device.\n");
}
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ UHD_LOG_DEBUG("MPMD", "Setting all timekeepers to 0...");
+ for (size_t mboard_idx = 0; mboard_idx < n_mboards; mboard_idx++) {
+ tree->access<time_spec_t>(fs_path("/mboards") / mboard_idx / "time" / "pps")
+ .set(time_spec_t(0.0));
+ }
- UHD_LOG_DEBUG("MPMD", "Waiting for next PPS edge...");
- std::this_thread::sleep_for(std::chrono::seconds(1));
+ UHD_LOG_DEBUG("MPMD", "Waiting for next PPS edge...");
+ std::this_thread::sleep_for(std::chrono::seconds(1));
- UHD_LOG_DEBUG("MPMD", "Verifying all timekeepers are aligned...");
- auto get_time_now = [tree](const size_t mb_index){
- return tree->access<time_spec_t>(
- fs_path("/mboards") / mb_index / "time/now"
- ).get();
- };
- for (size_t m = 1; m < n_mboards; m++){
- time_spec_t time_0 = get_time_now(0);
- time_spec_t time_i = get_time_now(m);
- if (time_i < time_0
- or (time_i - time_0) > time_spec_t(MPMD_CHDR_MAX_RTT)) {
- UHD_LOGGER_WARNING("MULTI_USRP") << boost::format(
- "Detected time deviation between board %d and board 0.\n"
- "Board 0 time is %f seconds.\n"
- "Board %d time is %f seconds.\n"
- ) % m % time_0.get_real_secs() % m % time_i.get_real_secs();
- }
+ UHD_LOG_DEBUG("MPMD", "Verifying all timekeepers are aligned...");
+ auto get_time_now = [tree](const size_t mb_index) {
+ return tree->access<time_spec_t>(fs_path("/mboards") / mb_index / "time/now")
+ .get();
+ };
+ for (size_t m = 1; m < n_mboards; m++) {
+ time_spec_t time_0 = get_time_now(0);
+ time_spec_t time_i = get_time_now(m);
+ if (time_i < time_0 or (time_i - time_0) > time_spec_t(MPMD_CHDR_MAX_RTT)) {
+ UHD_LOGGER_WARNING("MULTI_USRP")
+ << boost::format("Detected time deviation between board %d and board 0.\n"
+ "Board 0 time is %f seconds.\n"
+ "Board %d time is %f seconds.\n")
+ % m % time_0.get_real_secs() % m % time_i.get_real_secs();
}
}
+}
- /*! Throw an exception if compat numbers don't match.
- *
- * \param component Name of the component for which we're checking the
- * compat number (for logging and exceptions strings).
- * \param expected Tuple of 2 integers representing MAJOR.MINOR compat
- * number.
- * \param actual Tuple of 2 integers representing MAJOR.MINOR compat
- * number.
- * \param advice_on_failure A string that is appended to the error message
- * when compat number mismatches have occurred.
- */
- void assert_compat_number_throw(
- const std::string &component,
- const std::vector<size_t> &expected,
- const std::vector<size_t> &actual,
- const std::string& advice_on_failure=""
- ) {
- UHD_ASSERT_THROW(expected.size() == 2);
- UHD_ASSERT_THROW(actual.size() == 2);
- UHD_LOGGER_TRACE("MPMD")
- << "Checking " << component << " compat number. Expected: "
- << expected[0] << "." << expected[1]
- << " Actual: "
- << actual[0] << "." << actual[1]
- ;
+/*! Throw an exception if compat numbers don't match.
+ *
+ * \param component Name of the component for which we're checking the
+ * compat number (for logging and exceptions strings).
+ * \param expected Tuple of 2 integers representing MAJOR.MINOR compat
+ * number.
+ * \param actual Tuple of 2 integers representing MAJOR.MINOR compat
+ * number.
+ * \param advice_on_failure A string that is appended to the error message
+ * when compat number mismatches have occurred.
+ */
+void assert_compat_number_throw(const std::string& component,
+ const std::vector<size_t>& expected,
+ const std::vector<size_t>& actual,
+ const std::string& advice_on_failure = "")
+{
+ UHD_ASSERT_THROW(expected.size() == 2);
+ UHD_ASSERT_THROW(actual.size() == 2);
+ UHD_LOGGER_TRACE("MPMD") << "Checking " << component
+ << " compat number. Expected: " << expected[0] << "."
+ << expected[1] << " Actual: " << actual[0] << "."
+ << actual[1];
- if (actual[0] != expected[0]) {
- const std::string err_msg =
- str(boost::format("%s major compat number mismatch. "
- "Expected: %i.%i Actual: %i.%i.%s%s")
- % component
- % expected[0] % expected[1]
- % actual[0] % actual[1]
- % (advice_on_failure.empty() ? "" : " ")
- % advice_on_failure);
- UHD_LOG_ERROR("MPMD", err_msg);
- throw uhd::runtime_error(err_msg);
- }
- if (actual[1] < expected[1]) {
- const std::string err_msg =
- str(boost::format("%s minor compat number mismatch. "
- "Expected: %i.%i Actual: %i.%i.%s%s")
- % component
- % expected[0] % expected[1]
- % actual[0] % actual[1]
- % (advice_on_failure.empty() ? "" : " ")
- % advice_on_failure);
- UHD_LOG_ERROR("MPMD", err_msg);
- throw uhd::runtime_error(err_msg);
- }
- if (actual[1] > expected[1]) {
- const std::string err_msg =
- str(boost::format("%s minor compat number mismatch. "
- "Expected: %i.%i Actual: %i.%i")
- % component
- % expected[0] % expected[1]
- % actual[0] % actual[1]);
- UHD_LOG_WARNING("MPMD", err_msg);
- }
+ if (actual[0] != expected[0]) {
+ const std::string err_msg =
+ str(boost::format("%s major compat number mismatch. "
+ "Expected: %i.%i Actual: %i.%i.%s%s")
+ % component % expected[0] % expected[1] % actual[0] % actual[1]
+ % (advice_on_failure.empty() ? "" : " ") % advice_on_failure);
+ UHD_LOG_ERROR("MPMD", err_msg);
+ throw uhd::runtime_error(err_msg);
+ }
+ if (actual[1] < expected[1]) {
+ const std::string err_msg =
+ str(boost::format("%s minor compat number mismatch. "
+ "Expected: %i.%i Actual: %i.%i.%s%s")
+ % component % expected[0] % expected[1] % actual[0] % actual[1]
+ % (advice_on_failure.empty() ? "" : " ") % advice_on_failure);
+ UHD_LOG_ERROR("MPMD", err_msg);
+ throw uhd::runtime_error(err_msg);
+ }
+ if (actual[1] > expected[1]) {
+ const std::string err_msg =
+ str(boost::format("%s minor compat number mismatch. "
+ "Expected: %i.%i Actual: %i.%i")
+ % component % expected[0] % expected[1] % actual[0] % actual[1]);
+ UHD_LOG_WARNING("MPMD", err_msg);
}
}
+} // namespace
/*****************************************************************************
* Static class attributes
****************************************************************************/
-const std::string mpmd_impl::MPM_FINDALL_KEY = "find_all";
-const size_t mpmd_impl::MPM_DISCOVERY_PORT = 49600;
-const std::string mpmd_impl::MPM_DISCOVERY_PORT_KEY = "discovery_port";
-const size_t mpmd_impl::MPM_RPC_PORT = 49601;
-const std::string mpmd_impl::MPM_RPC_PORT_KEY = "rpc_port";
+const std::string mpmd_impl::MPM_FINDALL_KEY = "find_all";
+const size_t mpmd_impl::MPM_DISCOVERY_PORT = 49600;
+const std::string mpmd_impl::MPM_DISCOVERY_PORT_KEY = "discovery_port";
+const size_t mpmd_impl::MPM_RPC_PORT = 49601;
+const std::string mpmd_impl::MPM_RPC_PORT_KEY = "rpc_port";
const std::string mpmd_impl::MPM_RPC_GET_LAST_ERROR_CMD = "get_last_error";
-const std::string mpmd_impl::MPM_DISCOVERY_CMD = "MPM-DISC";
-const std::string mpmd_impl::MPM_ECHO_CMD = "MPM-ECHO";
+const std::string mpmd_impl::MPM_DISCOVERY_CMD = "MPM-DISC";
+const std::string mpmd_impl::MPM_ECHO_CMD = "MPM-ECHO";
/*****************************************************************************
* Structors
****************************************************************************/
mpmd_impl::mpmd_impl(const device_addr_t& device_args)
- : usrp::device3_impl()
- , _device_args(device_args)
+ : usrp::device3_impl(), _device_args(device_args)
{
const device_addrs_t mb_args = separate_device_addr(device_args);
- const size_t num_mboards = mb_args.size();
+ const size_t num_mboards = mb_args.size();
_mb.reserve(num_mboards);
const bool serialize_init = device_args.has_key("serialize_init");
- const bool skip_init = device_args.has_key("skip_init");
- UHD_LOGGER_INFO("MPMD")
- << "Initializing " << num_mboards << " device(s) "
- << (serialize_init ? "serially " : "in parallel ")
- << "with args: " << device_args.to_string();
+ const bool skip_init = device_args.has_key("skip_init");
+ UHD_LOGGER_INFO("MPMD") << "Initializing " << num_mboards << " device(s) "
+ << (serialize_init ? "serially " : "in parallel ")
+ << "with args: " << device_args.to_string();
// First, claim all the devices (so we own them and no one else can claim
// them).
@@ -202,8 +179,8 @@ mpmd_impl::mpmd_impl(const device_addr_t& device_args)
// can run _mb[*]->init() in parallel on all the _mb.
// This can *not* be parallelized.
std::vector<size_t> base_xport_addr(num_mboards, 2); // Starts at 2 [sic]
- for (size_t mb_i = 0; mb_i < num_mboards-1; ++mb_i) {
- base_xport_addr[mb_i+1] = base_xport_addr[mb_i] + _mb[mb_i]->num_xbars;
+ for (size_t mb_i = 0; mb_i < num_mboards - 1; ++mb_i) {
+ base_xport_addr[mb_i + 1] = base_xport_addr[mb_i] + _mb[mb_i]->num_xbars;
}
if (not skip_init) {
@@ -260,35 +237,28 @@ mpmd_impl::~mpmd_impl()
/*****************************************************************************
* Private methods
****************************************************************************/
-mpmd_mboard_impl::uptr mpmd_impl::claim_and_make(
- const uhd::device_addr_t& device_args
-) {
+mpmd_mboard_impl::uptr mpmd_impl::claim_and_make(const uhd::device_addr_t& device_args)
+{
const std::string rpc_addr = device_args.get(xport::MGMT_ADDR_KEY);
- UHD_LOGGER_DEBUG("MPMD")
- << "Device args: `" << device_args.to_string()
- << "'. RPC address: " << rpc_addr
- ;
+ UHD_LOGGER_DEBUG("MPMD") << "Device args: `" << device_args.to_string()
+ << "'. RPC address: " << rpc_addr;
if (rpc_addr.empty()) {
UHD_LOG_ERROR("MPMD",
"Could not determine RPC address from device args: "
- << device_args.to_string());
+ << device_args.to_string());
throw uhd::runtime_error("Could not determine device RPC address.");
}
return mpmd_mboard_impl::make(device_args, rpc_addr);
}
void mpmd_impl::setup_mb(
- mpmd_mboard_impl *mb,
- const size_t mb_index,
- const size_t base_xport_addr
-) {
- assert_compat_number_throw(
- "MPM",
+ mpmd_mboard_impl* mb, const size_t mb_index, const size_t base_xport_addr)
+{
+ assert_compat_number_throw("MPM",
MPM_COMPAT_NUM,
mb->rpc->request<std::vector<size_t>>("get_mpm_compat_num"),
- "Please update the version of MPM on your USRP device."
- );
+ "Please update the version of MPM on your USRP device.");
UHD_LOG_DEBUG("MPMD", "Initializing mboard " << mb_index);
mb->init();
@@ -297,94 +267,83 @@ void mpmd_impl::setup_mb(
}
}
-void mpmd_impl::setup_rfnoc_blocks(
- mpmd_mboard_impl* mb,
+void mpmd_impl::setup_rfnoc_blocks(mpmd_mboard_impl* mb,
const size_t mb_index,
- const uhd::device_addr_t& ctrl_xport_args
-) {
- UHD_LOG_TRACE("MPMD",
- "Mboard " << mb_index << " reports " << mb->num_xbars << " crossbar(s)."
- );
+ const uhd::device_addr_t& ctrl_xport_args)
+{
+ UHD_LOG_TRACE(
+ "MPMD", "Mboard " << mb_index << " reports " << mb->num_xbars << " crossbar(s).");
// TODO: The args apply to all xbars, which may or may not be true
for (size_t xbar_index = 0; xbar_index < mb->num_xbars; xbar_index++) {
// Pull the number of blocks and base port from the args, if available.
// Otherwise, get the values from MPM.
- const size_t num_blocks = ctrl_xport_args.has_key("rfnoc_num_blocks")
- ? ctrl_xport_args.cast<size_t>("rfnoc_num_blocks", 0)
- : mb->rpc->request<size_t>("get_num_blocks", xbar_index);
- const size_t base_port = ctrl_xport_args.has_key("rfnoc_base_port")
- ? ctrl_xport_args.cast<size_t>("rfnoc_base_port", 0)
- : mb->rpc->request<size_t>("get_base_port", xbar_index);
+ const size_t num_blocks =
+ ctrl_xport_args.has_key("rfnoc_num_blocks")
+ ? ctrl_xport_args.cast<size_t>("rfnoc_num_blocks", 0)
+ : mb->rpc->request<size_t>("get_num_blocks", xbar_index);
+ const size_t base_port =
+ ctrl_xport_args.has_key("rfnoc_base_port")
+ ? ctrl_xport_args.cast<size_t>("rfnoc_base_port", 0)
+ : mb->rpc->request<size_t>("get_base_port", xbar_index);
const size_t local_addr = mb->get_xbar_local_addr(xbar_index);
UHD_LOGGER_TRACE("MPMD")
<< "Enumerating RFNoC blocks for xbar " << xbar_index
- << ". Total blocks: " << num_blocks
- << " Base port: " << base_port
- << " Local address: " << local_addr
- ;
- if (ctrl_xport_args.has_key("rfnoc_num_blocks") or
- ctrl_xport_args.has_key("rfnoc_base_port")) {
+ << ". Total blocks: " << num_blocks << " Base port: " << base_port
+ << " Local address: " << local_addr;
+ if (ctrl_xport_args.has_key("rfnoc_num_blocks")
+ or ctrl_xport_args.has_key("rfnoc_base_port")) {
// TODO: Remove this warning once we're confident this is
// (relatively) safe and useful. Also add documentation to
// usrp_n3xx.dox
UHD_LOGGER_WARNING("MPMD")
<< "Overriding default RFNoC configuration. You are using an "
<< "experimental development feature, which may go away in "
- << "future versions."
- ;
+ << "future versions.";
}
try {
- enumerate_rfnoc_blocks(
- mb_index,
- num_blocks,
- base_port,
- uhd::sid_t(0, 0, local_addr, 0),
- ctrl_xport_args
- );
- } catch (const std::exception &ex) {
- UHD_LOGGER_ERROR("MPMD")
- << "Failure during block enumeration: "
- << ex.what();
+ enumerate_rfnoc_blocks(mb_index,
+ num_blocks,
+ base_port,
+ uhd::sid_t(0, 0, local_addr, 0),
+ ctrl_xport_args);
+ } catch (const std::exception& ex) {
+ UHD_LOGGER_ERROR("MPMD") << "Failure during block enumeration: " << ex.what();
throw uhd::runtime_error("Failed to run enumerate_rfnoc_blocks()");
}
}
}
void mpmd_impl::setup_rpc_blocks(
- const device_addr_t &block_args,
- const bool serialize_init
-) {
+ const device_addr_t& block_args, const bool serialize_init)
+{
std::vector<std::future<void>> task_list;
// If we don't force async, most compilers, at least now, will default to
// deferred.
- const auto launch_policy = serialize_init ?
- std::launch::deferred :
- std::launch::async;
+ const auto launch_policy = serialize_init ? std::launch::deferred
+ : std::launch::async;
// Preload all the tasks (they might start running on emplace_back)
- for (const auto &block_ctrl: _rfnoc_block_ctrl) {
+ for (const auto& block_ctrl : _rfnoc_block_ctrl) {
auto rpc_block_id = block_ctrl->get_block_id();
if (has_block<uhd::rfnoc::rpc_block_ctrl>(rpc_block_id)) {
const size_t mboard_idx = rpc_block_id.get_device_no();
auto rpc_block_ctrl =
get_block_ctrl<uhd::rfnoc::rpc_block_ctrl>(rpc_block_id);
auto rpc_sptr = _mb[mboard_idx]->rpc;
- task_list.emplace_back(std::async(launch_policy,
- [rpc_block_id, rpc_block_ctrl, &block_args, rpc_sptr](){
+ task_list.emplace_back(std::async(
+ launch_policy, [rpc_block_id, rpc_block_ctrl, &block_args, rpc_sptr]() {
UHD_LOGGER_DEBUG("MPMD")
<< "Adding RPC access to block: " << rpc_block_id
- << " Block args: " << block_args.to_string()
- ;
+ << " Block args: " << block_args.to_string();
rpc_block_ctrl->set_rpc_client(rpc_sptr, block_args);
- }
- ));
+ }));
}
}
// Execute all the calls to set_rpc_client(), either concurrently, or
// serially
- for (auto &task : task_list) {
+ for (auto& task : task_list) {
task.get();
}
}