diff options
author | Nick Foster <nick@nerdnetworks.org> | 2011-03-16 10:31:52 -0700 |
---|---|---|
committer | Nick Foster <nick@nerdnetworks.org> | 2011-03-16 10:31:52 -0700 |
commit | 9d752805de2020b6a8705c4abfce536620dcb760 (patch) | |
tree | acc90c66c52d41f0a75d396ec05f3246b52e2209 | |
parent | 3a1ad3f13c41a448083100ada6d4162a0092ee58 (diff) | |
download | uhd-9d752805de2020b6a8705c4abfce536620dcb760.tar.gz uhd-9d752805de2020b6a8705c4abfce536620dcb760.tar.bz2 uhd-9d752805de2020b6a8705c4abfce536620dcb760.zip |
USB zero copy impl: proper cleanup for canceled transfers -- wait for cancel before freeing
-rw-r--r-- | host/lib/transport/libusb1_zero_copy.cpp | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp index 87adece45..b425843fa 100644 --- a/host/lib/transport/libusb1_zero_copy.cpp +++ b/host/lib/transport/libusb1_zero_copy.cpp @@ -105,6 +105,12 @@ static void libusb_async_cb(libusb_transfer *lut){ (*static_cast<boost::function<void()> *>(lut->user_data))(); } +//! callback to free transfer upon cancellation +static void cancel_transfer_cb(libusb_transfer *lut) { + if(lut->status == LIBUSB_TRANSFER_CANCELLED) libusb_free_transfer(lut); + else std::cout << "cancel_transfer unexpected status " << lut->status << std::endl; +} + /*********************************************************************** * USB zero_copy device class **********************************************************************/ @@ -190,16 +196,18 @@ public: } ~libusb_zero_copy_impl(void){ - //shutdown the threads - _threads_running = false; - _thread_group.interrupt_all(); - _thread_group.join_all(); - //cancel and free all transfers BOOST_FOREACH(libusb_transfer *lut, _all_luts){ + lut->callback = &cancel_transfer_cb; libusb_cancel_transfer(lut); - libusb_free_transfer(lut); + while(lut->status != LIBUSB_TRANSFER_CANCELLED && lut->status != LIBUSB_TRANSFER_COMPLETED) { + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + } } + //shutdown the threads + _threads_running = false; + _thread_group.interrupt_all(); + _thread_group.join_all(); } managed_recv_buffer::sptr get_recv_buff(double timeout){ |