diff options
author | michael-west <michael.west@ettus.com> | 2017-03-08 17:16:10 -0800 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-04-05 17:26:28 -0700 |
commit | 7f7d9b04cfc59a8dd743ff3dc9c816b57675786e (patch) | |
tree | d98b2c26b0ef555c594bf46f3fc22c5258b1d0b2 /host/include | |
parent | 47d5f6651a05714f0cad55bd4c225a049abd5ef8 (diff) | |
download | uhd-7f7d9b04cfc59a8dd743ff3dc9c816b57675786e.tar.gz uhd-7f7d9b04cfc59a8dd743ff3dc9c816b57675786e.tar.bz2 uhd-7f7d9b04cfc59a8dd743ff3dc9c816b57675786e.zip |
Fix bounded buffer functions so they don't release the lock before waiting on condition variables.
Diffstat (limited to 'host/include')
-rw-r--r-- | host/include/uhd/transport/bounded_buffer.ipp | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp index 35ffb293b..daca3f04f 100644 --- a/host/include/uhd/transport/bounded_buffer.ipp +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -28,7 +28,8 @@ namespace uhd{ namespace transport{ - template <typename elem_type> class bounded_buffer_detail : boost::noncopyable{ + template <typename elem_type> class bounded_buffer_detail : boost::noncopyable + { public: bounded_buffer_detail(size_t capacity): @@ -38,79 +39,97 @@ namespace uhd{ namespace transport{ _not_empty_fcn = boost::bind(&bounded_buffer_detail<elem_type>::not_empty, this); } - UHD_INLINE bool push_with_haste(const elem_type &elem){ + UHD_INLINE bool push_with_haste(const elem_type &elem) + { boost::mutex::scoped_lock lock(_mutex); - if (_buffer.full()) return false; + if (_buffer.full()) + { + return false; + } _buffer.push_front(elem); - lock.unlock(); _empty_cond.notify_one(); return true; } - UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ + UHD_INLINE bool push_with_pop_on_full(const elem_type &elem) + { boost::mutex::scoped_lock lock(_mutex); - if (_buffer.full()){ + if (_buffer.full()) + { _buffer.pop_back(); _buffer.push_front(elem); - lock.unlock(); _empty_cond.notify_one(); return false; } - else{ + else { _buffer.push_front(elem); - lock.unlock(); _empty_cond.notify_one(); return true; } } - UHD_INLINE void push_with_wait(const elem_type &elem){ - if (this->push_with_haste(elem)) return; + UHD_INLINE void push_with_wait(const elem_type &elem) + { boost::mutex::scoped_lock lock(_mutex); - _full_cond.wait(lock, _not_full_fcn); + if (_buffer.full()) + { + _full_cond.wait(lock, _not_full_fcn); + } _buffer.push_front(elem); - lock.unlock(); _empty_cond.notify_one(); } - UHD_INLINE bool push_with_timed_wait(const elem_type &elem, double timeout){ - if (this->push_with_haste(elem)) return true; + UHD_INLINE bool push_with_timed_wait(const elem_type &elem, double timeout) + { boost::mutex::scoped_lock lock(_mutex); - if (not _full_cond.timed_wait( - lock, to_time_dur(timeout), _not_full_fcn - )) return false; + if (_buffer.full()) + { + if (not _full_cond.timed_wait(lock, + to_time_dur(timeout), _not_full_fcn)) + { + return false; + } + } _buffer.push_front(elem); - lock.unlock(); _empty_cond.notify_one(); return true; } - UHD_INLINE bool pop_with_haste(elem_type &elem){ + UHD_INLINE bool pop_with_haste(elem_type &elem) + { boost::mutex::scoped_lock lock(_mutex); - if (_buffer.empty()) return false; + if (_buffer.empty()) + { + return false; + } this->pop_back(elem); - lock.unlock(); _full_cond.notify_one(); return true; } - UHD_INLINE void pop_with_wait(elem_type &elem){ - if (this->pop_with_haste(elem)) return; + UHD_INLINE void pop_with_wait(elem_type &elem) + { boost::mutex::scoped_lock lock(_mutex); - _empty_cond.wait(lock, _not_empty_fcn); + if (_buffer.empty()) + { + _empty_cond.wait(lock, _not_empty_fcn); + } this->pop_back(elem); - lock.unlock(); _full_cond.notify_one(); } - UHD_INLINE bool pop_with_timed_wait(elem_type &elem, double timeout){ - if (this->pop_with_haste(elem)) return true; + UHD_INLINE bool pop_with_timed_wait(elem_type &elem, double timeout) + { boost::mutex::scoped_lock lock(_mutex); - if (not _empty_cond.timed_wait( - lock, to_time_dur(timeout), _not_empty_fcn - )) return false; + if (_buffer.empty()) + { + if (not _empty_cond.timed_wait(lock, to_time_dur(timeout), + _not_empty_fcn)) + { + return false; + } + } this->pop_back(elem); - lock.unlock(); _full_cond.notify_one(); return true; } @@ -131,13 +150,15 @@ namespace uhd{ namespace transport{ * 2) assign the back element to empty * 3) pop the back to move the counter */ - UHD_INLINE void pop_back(elem_type &elem){ + UHD_INLINE void pop_back(elem_type &elem) + { elem = _buffer.back(); _buffer.back() = elem_type(); _buffer.pop_back(); } - static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ + static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout) + { return boost::posix_time::microseconds(long(timeout*1e6)); } |