1. _running is guarded with a lock in the rtl event loop epilogue. this prevents a possible hang that could arise from _buf_cond being notified prior to work() waiting on _buf_cond, but after work() checks _running.
2. _buf_used is guarded with a lock in the work function to prevent it from spuriously reading zero if it is nonatomically written from the rtl event callback. --- lib/rtl/rtl_source_c.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/lib/rtl/rtl_source_c.cc b/lib/rtl/rtl_source_c.cc index a371464..bbd0140 100644 --- a/lib/rtl/rtl_source_c.cc +++ b/lib/rtl/rtl_source_c.cc @@ -323,7 +323,11 @@ void rtl_source_c::rtlsdr_wait() { int ret = rtlsdr_read_async( _dev, _rtlsdr_callback, (void *)this, _buf_num, _buf_len );
- _running = false; + { + boost::mutex::scoped_lock lock( _buf_mutex ); + + _running = false; + }
if ( ret != 0 ) std::cerr << "rtlsdr_read_async returned with " << ret << std::endl; @@ -347,7 +351,7 @@ int rtl_source_c::work( int noutput_items, if (!_running) return WORK_DONE;
- while (noutput_items && _buf_used) { + while (noutput_items) { const int nout = std::min(noutput_items, _samp_avail); const unsigned char *buf = _buf[_buf_head] + _buf_offset * 2;
@@ -363,6 +367,9 @@ int rtl_source_c::work( int noutput_items,
_buf_head = (_buf_head + 1) % _buf_num; _buf_used--; + + if (_buf_used == 0) + break; } _samp_avail = _buf_len / BYTES_PER_SAMPLE; _buf_offset = 0;