26
26
27
27
#include < libfreenect2/usb/transfer_pool.h>
28
28
#include < iostream>
29
- #include < algorithm>
30
29
31
30
namespace libfreenect2
32
31
{
@@ -60,11 +59,11 @@ void TransferPool::disableSubmission()
60
59
61
60
void TransferPool::deallocate ()
62
61
{
63
- for (TransferQueue::iterator it = idle_transfers_ .begin (); it != idle_transfers_ .end (); ++it)
62
+ for (TransferQueue::iterator it = transfers_ .begin (); it != transfers_ .end (); ++it)
64
63
{
65
- libusb_free_transfer (*it );
64
+ libusb_free_transfer (it-> transfer );
66
65
}
67
- idle_transfers_ .clear ();
66
+ transfers_ .clear ();
68
67
69
68
if (buffer_ != 0 )
70
69
{
@@ -82,44 +81,49 @@ void TransferPool::submit(size_t num_parallel_transfers)
82
81
return ;
83
82
}
84
83
85
- if (idle_transfers_ .size () < num_parallel_transfers)
84
+ if (transfers_ .size () < num_parallel_transfers)
86
85
{
87
86
std::cerr << " [TransferPool::submit] too few idle transfers!" << std::endl;
88
87
}
89
88
90
89
for (size_t i = 0 ; i < num_parallel_transfers; ++i)
91
90
{
92
- libusb_transfer *transfer = idle_transfers_. front () ;
93
- idle_transfers_. pop_front ( );
91
+ libusb_transfer *transfer = transfers_[i]. transfer ;
92
+ transfers_[i]. setStopped ( false );
94
93
95
94
int r = libusb_submit_transfer (transfer);
96
95
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)
103
97
{
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 ) ;
106
100
}
107
101
}
108
102
}
109
103
110
104
void TransferPool::cancel ()
111
105
{
112
- for (TransferQueue::iterator it = pending_transfers_ .begin (); it != pending_transfers_ .end (); ++it)
106
+ for (TransferQueue::iterator it = transfers_ .begin (); it != transfers_ .end (); ++it)
113
107
{
114
- int r = libusb_cancel_transfer (*it );
108
+ int r = libusb_cancel_transfer (it-> transfer );
115
109
116
- if (r != LIBUSB_SUCCESS)
110
+ if (r != LIBUSB_SUCCESS && r != LIBUSB_ERROR_NOT_FOUND )
117
111
{
118
- // TODO: error reporting
112
+ std::cerr << " [TransferPool::cancel] failed to cancel transfer: " << libusb_error_name (r) << std::endl;
119
113
}
120
114
}
121
115
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
+ }
123
127
}
124
128
125
129
void TransferPool::setCallback (DataCallback *callback)
@@ -131,6 +135,7 @@ void TransferPool::allocateTransfers(size_t num_transfers, size_t transfer_size)
131
135
{
132
136
buffer_size_ = num_transfers * transfer_size;
133
137
buffer_ = new unsigned char [buffer_size_];
138
+ transfers_.reserve (num_transfers);
134
139
135
140
unsigned char *ptr = buffer_;
136
141
@@ -139,45 +144,51 @@ void TransferPool::allocateTransfers(size_t num_transfers, size_t transfer_size)
139
144
libusb_transfer *transfer = allocateTransfer ();
140
145
fillTransfer (transfer);
141
146
147
+ transfers_.push_back (TransferPool::Transfer (transfer, this ));
148
+
142
149
transfer->dev_handle = device_handle_;
143
150
transfer->endpoint = device_endpoint_;
144
151
transfer->buffer = ptr;
145
152
transfer->length = transfer_size;
146
153
transfer->timeout = 1000 ;
147
154
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 ();
151
156
152
157
ptr += transfer_size;
153
158
}
154
159
}
155
160
156
161
void TransferPool::onTransferCompleteStatic (libusb_transfer* transfer)
157
162
{
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);
159
165
}
160
166
161
- void TransferPool::onTransferComplete (libusb_transfer* transfer )
167
+ void TransferPool::onTransferComplete (TransferPool::Transfer* t )
162
168
{
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)
167
170
{
168
- // TODO: error reporting
171
+ t->setStopped (true );
172
+ return ;
169
173
}
170
174
171
- pending_transfers_.erase (it);
172
-
173
175
// process data
174
- processTransfer (transfer);
176
+ processTransfer (t-> transfer );
175
177
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 );
178
186
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
+ }
181
192
}
182
193
183
194
BulkTransferPool::BulkTransferPool (libusb_device_handle* device_handle, unsigned char device_endpoint) :
0 commit comments