mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
lib: Remove boost::thread usage from USB transports
All the USB-based USRPs use boost::thread constructs, which are removed
with this commit. The following changes are applied:
- boost::condition is replaced with std::condition_variable
- This requires shifting timeout values from boost::posix_time to
std::chrono
- boost::condition::timed_wait() is replaced by
std::condition_variable::wait_for(), which returns a std::cv_status
instead of bool.
- msg_task used a boost::barrier to check for the correct start of the
underlying thread, which is removed to a simple check of the
integrated boolean.
This commit is contained in:
parent
1edb3a4c0a
commit
3855516f6f
@ -12,9 +12,10 @@
|
|||||||
#include <uhd/transport/buffer_pool.hpp>
|
#include <uhd/transport/buffer_pool.hpp>
|
||||||
#include <uhd/transport/usb_zero_copy.hpp>
|
#include <uhd/transport/usb_zero_copy.hpp>
|
||||||
#include <uhd/utils/log.hpp>
|
#include <uhd/utils/log.hpp>
|
||||||
|
#include <condition_variable>
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -50,7 +51,7 @@ struct lut_result_t
|
|||||||
libusb_transfer_status status;
|
libusb_transfer_status status;
|
||||||
int actual_length;
|
int actual_length;
|
||||||
std::mutex mut;
|
std::mutex mut;
|
||||||
boost::condition usb_transfer_complete;
|
std::condition_variable usb_transfer_complete;
|
||||||
|
|
||||||
#ifdef UHD_TXRX_DEBUG_PRINTS
|
#ifdef UHD_TXRX_DEBUG_PRINTS
|
||||||
// These are fore debugging
|
// These are fore debugging
|
||||||
@ -60,7 +61,7 @@ struct lut_result_t
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Created to be used as an argument to boost::condition_variable::timed_wait() function
|
// Created to be used as an argument to std::condition_variable::wait_for() function
|
||||||
struct lut_result_completed
|
struct lut_result_completed
|
||||||
{
|
{
|
||||||
const lut_result_t& _result;
|
const lut_result_t& _result;
|
||||||
@ -184,11 +185,9 @@ public:
|
|||||||
if (timeout < 0.0) {
|
if (timeout < 0.0) {
|
||||||
result.usb_transfer_complete.wait(lock);
|
result.usb_transfer_complete.wait(lock);
|
||||||
} else {
|
} else {
|
||||||
const boost::system_time timeout_time =
|
result.usb_transfer_complete.wait_for(lock,
|
||||||
boost::get_system_time()
|
std::chrono::microseconds(static_cast<int64_t>(timeout * 1e6)),
|
||||||
+ boost::posix_time::microseconds(long(timeout * 1000000));
|
lut_result_completed(result));
|
||||||
result.usb_transfer_complete.timed_wait(
|
|
||||||
lock, timeout_time, lut_result_completed(result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (result.completed > 0);
|
return (result.completed > 0);
|
||||||
@ -317,8 +316,8 @@ public:
|
|||||||
|
|
||||||
std::unique_lock<std::mutex> queue_lock(_queue_mutex);
|
std::unique_lock<std::mutex> queue_lock(_queue_mutex);
|
||||||
if (_enqueued.empty()) {
|
if (_enqueued.empty()) {
|
||||||
_buff_ready_cond.timed_wait(
|
_buff_ready_cond.wait_for(queue_lock,
|
||||||
queue_lock, boost::posix_time::microseconds(long(timeout * 1e6)));
|
std::chrono::microseconds(static_cast<int64_t>(timeout * 1e6)));
|
||||||
}
|
}
|
||||||
if (_enqueued.empty())
|
if (_enqueued.empty())
|
||||||
return buff;
|
return buff;
|
||||||
@ -352,7 +351,7 @@ private:
|
|||||||
std::vector<std::shared_ptr<libusb_zero_copy_mb>> _mb_pool;
|
std::vector<std::shared_ptr<libusb_zero_copy_mb>> _mb_pool;
|
||||||
|
|
||||||
std::mutex _queue_mutex;
|
std::mutex _queue_mutex;
|
||||||
boost::condition _buff_ready_cond;
|
std::condition_variable _buff_ready_cond;
|
||||||
std::mutex _get_buff_mutex;
|
std::mutex _get_buff_mutex;
|
||||||
|
|
||||||
//! why 2 queues? there is room in the future to have > N buffers but only N in flight
|
//! why 2 queues? there is room in the future to have > N buffers but only N in flight
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
#include <uhd/utils/log.hpp>
|
#include <uhd/utils/log.hpp>
|
||||||
#include <uhd/utils/tasks.hpp>
|
#include <uhd/utils/tasks.hpp>
|
||||||
#include <uhdlib/utils/atomic.hpp>
|
#include <uhdlib/utils/atomic.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -21,8 +21,7 @@
|
|||||||
using namespace uhd;
|
using namespace uhd;
|
||||||
using namespace uhd::transport;
|
using namespace uhd::transport;
|
||||||
|
|
||||||
static const boost::posix_time::time_duration AUTOFLUSH_TIMEOUT(
|
constexpr std::chrono::milliseconds AUTOFLUSH_TIMEOUT{1};
|
||||||
boost::posix_time::milliseconds(1));
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* USB zero copy wrapper - managed receive buffer
|
* USB zero copy wrapper - managed receive buffer
|
||||||
@ -147,7 +146,7 @@ private:
|
|||||||
|
|
||||||
// private variables for auto flusher
|
// private variables for auto flusher
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
boost::condition _cond;
|
std::condition_variable _cond;
|
||||||
uhd::task::sptr _task;
|
uhd::task::sptr _task;
|
||||||
bool _ok_to_auto_flush;
|
bool _ok_to_auto_flush;
|
||||||
|
|
||||||
@ -158,7 +157,8 @@ private:
|
|||||||
void auto_flush(void)
|
void auto_flush(void)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
const bool timeout = not _cond.timed_wait(lock, AUTOFLUSH_TIMEOUT);
|
const bool timeout = _cond.wait_for(lock, AUTOFLUSH_TIMEOUT)
|
||||||
|
== std::cv_status::timeout;
|
||||||
if (timeout and _ok_to_auto_flush and _last_send_buff and _bytes_in_buffer != 0) {
|
if (timeout and _ok_to_auto_flush and _last_send_buff and _bytes_in_buffer != 0) {
|
||||||
_last_send_buff->commit(_bytes_in_buffer);
|
_last_send_buff->commit(_bytes_in_buffer);
|
||||||
_last_send_buff.reset();
|
_last_send_buff.reset();
|
||||||
|
|||||||
@ -640,7 +640,6 @@ double usrp1_impl::update_tx_dsp_freq(const size_t dspno, const double freq)
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
bool usrp1_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout)
|
bool usrp1_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout)
|
||||||
{
|
{
|
||||||
boost::this_thread::disable_interruption di; // disable because the wait can throw
|
|
||||||
return _soft_time_ctrl->get_async_queue().pop_with_timed_wait(
|
return _soft_time_ctrl->get_async_queue().pop_with_timed_wait(
|
||||||
async_metadata, timeout);
|
async_metadata, timeout);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
#include "soft_time_ctrl.hpp"
|
#include "soft_time_ctrl.hpp"
|
||||||
#include <uhd/utils/tasks.hpp>
|
#include <uhd/utils/tasks.hpp>
|
||||||
#include <uhdlib/utils/system_time.hpp>
|
#include <uhdlib/utils/system_time.hpp>
|
||||||
#include <boost/thread/condition.hpp>
|
#include <condition_variable>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -71,10 +71,11 @@ public:
|
|||||||
UHD_INLINE void sleep_until_time(
|
UHD_INLINE void sleep_until_time(
|
||||||
std::unique_lock<std::mutex>& lock, const time_spec_t& time)
|
std::unique_lock<std::mutex>& lock, const time_spec_t& time)
|
||||||
{
|
{
|
||||||
boost::condition cond;
|
std::condition_variable cond;
|
||||||
// use a condition variable to unlock, sleep, lock
|
// use a condition variable to unlock, sleep, lock
|
||||||
const double seconds_to_sleep = (time - time_now()).get_real_secs();
|
const double seconds_to_sleep = (time - time_now()).get_real_secs();
|
||||||
cond.timed_wait(lock, pt::microseconds(long(seconds_to_sleep * 1e6)));
|
cond.wait_for(lock,
|
||||||
|
std::chrono::microseconds(static_cast<int64_t>(seconds_to_sleep * 1e6)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
|||||||
@ -19,9 +19,6 @@
|
|||||||
#include <uhdlib/asio.hpp>
|
#include <uhdlib/asio.hpp>
|
||||||
#include <uhdlib/usrp/common/async_packet_handler.hpp>
|
#include <uhdlib/usrp/common/async_packet_handler.hpp>
|
||||||
#include <uhdlib/usrp/common/validate_subdev_spec.hpp>
|
#include <uhdlib/usrp/common/validate_subdev_spec.hpp>
|
||||||
#include <boost/format.hpp>
|
|
||||||
#include <boost/thread/mutex.hpp>
|
|
||||||
#include <boost/thread/thread.hpp>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -31,16 +28,6 @@
|
|||||||
using namespace uhd;
|
using namespace uhd;
|
||||||
using namespace uhd::usrp;
|
using namespace uhd::usrp;
|
||||||
using namespace uhd::transport;
|
using namespace uhd::transport;
|
||||||
namespace asio = boost::asio;
|
|
||||||
namespace pt = boost::posix_time;
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* helpers
|
|
||||||
**********************************************************************/
|
|
||||||
static UHD_INLINE pt::time_duration to_time_dur(double timeout)
|
|
||||||
{
|
|
||||||
return pt::microseconds(long(timeout * 1e6));
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* constants
|
* constants
|
||||||
@ -95,8 +82,9 @@ public:
|
|||||||
std::unique_lock<std::mutex> lock(_fc_mutex);
|
std::unique_lock<std::mutex> lock(_fc_mutex);
|
||||||
if (this->ready())
|
if (this->ready())
|
||||||
return true;
|
return true;
|
||||||
boost::this_thread::disable_interruption di; // disable because the wait can throw
|
return _fc_cond.wait_for(lock,
|
||||||
return _fc_cond.timed_wait(lock, to_time_dur(timeout), _ready_fcn);
|
std::chrono::microseconds(static_cast<int64_t>(timeout * 1e6)),
|
||||||
|
_ready_fcn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -118,7 +106,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::mutex _fc_mutex;
|
std::mutex _fc_mutex;
|
||||||
boost::condition _fc_cond;
|
std::condition_variable _fc_cond;
|
||||||
seq_type _last_seq_out, _last_seq_ack;
|
seq_type _last_seq_out, _last_seq_ack;
|
||||||
const seq_type _max_seqs_out;
|
const seq_type _max_seqs_out;
|
||||||
std::function<bool(void)> _ready_fcn;
|
std::function<bool(void)> _ready_fcn;
|
||||||
@ -388,7 +376,6 @@ void usrp2_impl::update_tx_subdev_spec(
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
bool usrp2_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout)
|
bool usrp2_impl::recv_async_msg(async_metadata_t& async_metadata, double timeout)
|
||||||
{
|
{
|
||||||
boost::this_thread::disable_interruption di; // disable because the wait can throw
|
|
||||||
return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout);
|
return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,9 +397,9 @@ void usrp2_impl::program_stream_dest(
|
|||||||
// user has provided an alternative address and port for destination
|
// user has provided an alternative address and port for destination
|
||||||
if (args.args.has_key("addr") and args.args.has_key("port")) {
|
if (args.args.has_key("addr") and args.args.has_key("port")) {
|
||||||
UHD_LOGGER_INFO("USRP2")
|
UHD_LOGGER_INFO("USRP2")
|
||||||
<< boost::format("Programming streaming destination for custom address. "
|
<< "Programming streaming destination for custom address. "
|
||||||
"IPv4 Address: %s, UDP Port: %s")
|
"IPv4 Address: "
|
||||||
% args.args["addr"] % args.args["port"];
|
<< args.args["addr"] << ", UDP Port: " << args.args["port"];
|
||||||
|
|
||||||
asio::io_context io_context;
|
asio::io_context io_context;
|
||||||
asio::ip::udp::resolver resolver(io_context);
|
asio::ip::udp::resolver resolver(io_context);
|
||||||
|
|||||||
@ -10,8 +10,8 @@
|
|||||||
#include <uhd/utils/msg_task.hpp>
|
#include <uhd/utils/msg_task.hpp>
|
||||||
#include <uhd/utils/tasks.hpp>
|
#include <uhd/utils/tasks.hpp>
|
||||||
#include <uhd/utils/thread.hpp>
|
#include <uhd/utils/thread.hpp>
|
||||||
#include <boost/thread/barrier.hpp>
|
#include <condition_variable>
|
||||||
#include <boost/thread/thread.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -85,18 +85,21 @@ msg_task::~msg_task(void)
|
|||||||
class msg_task_impl : public msg_task
|
class msg_task_impl : public msg_task
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
msg_task_impl(const task_fcn_type& task_fcn) : _spawn_barrier(2)
|
msg_task_impl(const task_fcn_type& task_fcn)
|
||||||
|
: _running(false), _thread([this, task_fcn]() { this->task_loop(task_fcn); })
|
||||||
{
|
{
|
||||||
(void)_thread_group.create_thread(
|
// Wait for the thread to successfully start
|
||||||
std::bind(&msg_task_impl::task_loop, this, task_fcn));
|
std::unique_lock<std::mutex> _l(_mutex);
|
||||||
_spawn_barrier.wait();
|
|
||||||
|
_start_cv.wait(_l, [this]() { return _running.load(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
~msg_task_impl(void) override
|
~msg_task_impl(void) override
|
||||||
{
|
{
|
||||||
_running = false;
|
_running = false;
|
||||||
_thread_group.interrupt_all();
|
if (_thread.joinable()) {
|
||||||
_thread_group.join_all();
|
_thread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -123,7 +126,7 @@ private:
|
|||||||
void task_loop(const task_fcn_type& task_fcn)
|
void task_loop(const task_fcn_type& task_fcn)
|
||||||
{
|
{
|
||||||
_running = true;
|
_running = true;
|
||||||
_spawn_barrier.wait();
|
_start_cv.notify_one();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (_running) {
|
while (_running) {
|
||||||
@ -138,8 +141,6 @@ private:
|
|||||||
_dump_queue.push_back(buff.get());
|
_dump_queue.push_back(buff.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const boost::thread_interrupted&) {
|
|
||||||
// this is an ok way to exit the task loop
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
do_error_msg(e.what());
|
do_error_msg(e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@ -157,9 +158,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
boost::thread_group _thread_group;
|
std::condition_variable _start_cv;
|
||||||
boost::barrier _spawn_barrier;
|
std::atomic<bool> _running;
|
||||||
bool _running;
|
std::thread _thread;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This queue holds stranded messages until a radio_ctrl_core grabs them via
|
* This queue holds stranded messages until a radio_ctrl_core grabs them via
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user