2626
2727#include < libfreenect2/usb/transfer_pool.h>
2828#include < iostream>
29- #include < algorithm>
3029
3130namespace libfreenect2
3231{
@@ -60,11 +59,11 @@ void TransferPool::disableSubmission()
6059
6160void TransferPool::deallocate ()
6261{
63- for (TransferQueue::iterator it = idle_transfers_ .begin (); it != idle_transfers_ .end (); ++it)
62+ for (TransferQueue::iterator it = transfers_ .begin (); it != transfers_ .end (); ++it)
6463 {
65- libusb_free_transfer (*it );
64+ libusb_free_transfer (it-> transfer );
6665 }
67- idle_transfers_ .clear ();
66+ transfers_ .clear ();
6867
6968 if (buffer_ != 0 )
7069 {
@@ -82,44 +81,49 @@ void TransferPool::submit(size_t num_parallel_transfers)
8281 return ;
8382 }
8483
85- if (idle_transfers_ .size () < num_parallel_transfers)
84+ if (transfers_ .size () < num_parallel_transfers)
8685 {
8786 std::cerr << " [TransferPool::submit] too few idle transfers!" << std::endl;
8887 }
8988
9089 for (size_t i = 0 ; i < num_parallel_transfers; ++i)
9190 {
92- libusb_transfer *transfer = idle_transfers_. front () ;
93- idle_transfers_. pop_front ( );
91+ libusb_transfer *transfer = transfers_[i]. transfer ;
92+ transfers_[i]. setStopped ( false );
9493
9594 int r = libusb_submit_transfer (transfer);
9695
97- // put transfer in pending queue on success otherwise put it back in the idle queue
98- if (r == LIBUSB_SUCCESS)
99- {
100- pending_transfers_.push_back (transfer);
101- }
102- else
96+ if (r != LIBUSB_SUCCESS)
10397 {
104- idle_transfers_. push_back ( transfer) ;
105- std::cerr << " [TransferPool::submit] failed to submit transfer " << std::endl ;
98+ std::cerr << " [TransferPool::submit] failed to submit transfer: " << libusb_error_name (r) << std::endl ;
99+ transfers_[i]. setStopped ( true ) ;
106100 }
107101 }
108102}
109103
110104void TransferPool::cancel ()
111105{
112- for (TransferQueue::iterator it = pending_transfers_ .begin (); it != pending_transfers_ .end (); ++it)
106+ for (TransferQueue::iterator it = transfers_ .begin (); it != transfers_ .end (); ++it)
113107 {
114- int r = libusb_cancel_transfer (*it );
108+ int r = libusb_cancel_transfer (it-> transfer );
115109
116- if (r != LIBUSB_SUCCESS)
110+ if (r != LIBUSB_SUCCESS && r != LIBUSB_ERROR_NOT_FOUND )
117111 {
118- // TODO: error reporting
112+ std::cerr << " [TransferPool::cancel] failed to cancel transfer: " << libusb_error_name (r) << std::endl;
119113 }
120114 }
121115
122- // idle_transfers_.insert(idle_transfers_.end(), pending_transfers_.begin(), pending_transfers_.end());
116+ for (;;)
117+ {
118+ libfreenect2::this_thread::sleep_for (libfreenect2::chrono::milliseconds (100 ));
119+ size_t stopped_transfers = 0 ;
120+ for (TransferQueue::iterator it = transfers_.begin (); it != transfers_.end (); ++it)
121+ stopped_transfers += it->getStopped ();
122+ if (stopped_transfers == transfers_.size ())
123+ break ;
124+ std::cerr << " [TransferPool::cancel] waiting for transfer cancellation" << std::endl;
125+ libfreenect2::this_thread::sleep_for (libfreenect2::chrono::milliseconds (1000 ));
126+ }
123127}
124128
125129void TransferPool::setCallback (DataCallback *callback)
@@ -131,6 +135,7 @@ void TransferPool::allocateTransfers(size_t num_transfers, size_t transfer_size)
131135{
132136 buffer_size_ = num_transfers * transfer_size;
133137 buffer_ = new unsigned char [buffer_size_];
138+ transfers_.reserve (num_transfers);
134139
135140 unsigned char *ptr = buffer_;
136141
@@ -139,45 +144,51 @@ void TransferPool::allocateTransfers(size_t num_transfers, size_t transfer_size)
139144 libusb_transfer *transfer = allocateTransfer ();
140145 fillTransfer (transfer);
141146
147+ transfers_.push_back (TransferPool::Transfer (transfer, this ));
148+
142149 transfer->dev_handle = device_handle_;
143150 transfer->endpoint = device_endpoint_;
144151 transfer->buffer = ptr;
145152 transfer->length = transfer_size;
146153 transfer->timeout = 1000 ;
147154 transfer->callback = (libusb_transfer_cb_fn) &TransferPool::onTransferCompleteStatic;
148- transfer->user_data = this ;
149-
150- idle_transfers_.push_back (transfer);
155+ transfer->user_data = &transfers_.back ();
151156
152157 ptr += transfer_size;
153158 }
154159}
155160
156161void TransferPool::onTransferCompleteStatic (libusb_transfer* transfer)
157162{
158- reinterpret_cast <TransferPool*>(transfer->user_data )->onTransferComplete (transfer);
163+ TransferPool::Transfer *t = reinterpret_cast <TransferPool::Transfer*>(transfer->user_data );
164+ t->pool ->onTransferComplete (t);
159165}
160166
161- void TransferPool::onTransferComplete (libusb_transfer* transfer )
167+ void TransferPool::onTransferComplete (TransferPool::Transfer* t )
162168{
163- // remove transfer from pending queue - should be fast as it is somewhere at the front
164- TransferQueue::iterator it = std::find (pending_transfers_.begin (), pending_transfers_.end (), transfer);
165-
166- if (it == pending_transfers_.end ())
169+ if (t->transfer ->status == LIBUSB_TRANSFER_CANCELLED)
167170 {
168- // TODO: error reporting
171+ t->setStopped (true );
172+ return ;
169173 }
170174
171- pending_transfers_.erase (it);
172-
173175 // process data
174- processTransfer (transfer);
176+ processTransfer (t-> transfer );
175177
176- // put transfer back in idle queue
177- idle_transfers_.push_back (transfer);
178+ if (!enable_submit_)
179+ {
180+ t->setStopped (true );
181+ return ;
182+ }
183+
184+ // resubmit self
185+ int r = libusb_submit_transfer (t->transfer );
178186
179- // submit new transfer
180- submit (1 );
187+ if (r != LIBUSB_SUCCESS)
188+ {
189+ std::cerr << " [TransferPool::onTransferComplete] failed to submit transfer: " << libusb_error_name (r) << std::endl;
190+ t->setStopped (true );
191+ }
181192}
182193
183194BulkTransferPool::BulkTransferPool (libusb_device_handle* device_handle, unsigned char device_endpoint) :
0 commit comments