-
Notifications
You must be signed in to change notification settings - Fork 221
usbdmx: Add support for having multiple inflight transfers #1627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Changes:
In theory this should mean widget specific classes shouldn't even be able to notice what the transfer queue depth actually is, so maybe we can just turn this on across all widgets. |
009b767 to
4d32528
Compare
|
Changes:
|
1a0abb6 to
8f0f2e3
Compare
peternewman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some initial comments
| inflight_set::iterator i = m_inflight.find(transfer); | ||
| if (i == m_inflight.end()) { // not found | ||
| OLA_WARN << "Mismatched libusb transfer: " | ||
| << transfer << " not in inflight set"; | ||
| return; | ||
| } | ||
|
|
||
| m_inflight.erase(i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be easier replacing with our ola::STLLookupAndRemove? http://docs.openlighting.org/ola/doc/latest/group__stl.html#ga7a896801adfcea56e630bd5007c135e1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't seem to work for sets? Even if it would it's a bit akward. Since STLLookupAndRemove doesn't check if the value arg is NULL I'd have to provide a dummy.
./include/ola/stl/STLUtils.h:393:6: note: candidate: ‘template<class T1> bool ola::STLLookupAndRemove(T1*, const typename T1::key_type&, typename T1::mapped_type*)’
bool STLLookupAndRemove(T1 *container,
^~~~~~~~~~~~~~~~~~
./include/ola/stl/STLUtils.h:393:6: note: template argument deduction/substitution failed:
plugins/usbdmx/AsyncUsbTransceiverBase.cpp:52:59: note: mismatched types ‘T1*’ and ‘std::set<libusb_transfer*>’
if (STLLookupAndRemove(m_inflight, transfer, transfer_)) { // not found
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies, wrong command, after looking more carefully ola::STLRemove will do what you want:
http://docs.openlighting.org/ola/doc/latest/group__stl.html#ga6bab5568a6d6ef14d4faccea9eddd41b
Or is there a risk of multiple equal transfers in the set (I assume they have a unique ID, but maybe not)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or is there a risk of multiple equal transfers in the set (I assume they have a unique ID, but maybe not)?
Reading more carefully, they have to be unique, so no risk there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to push back on this, but honestly I don't see STLRemove having any advantage over calling .erase() here. All this change would do is invalidate my testing and perform another unnecessary traversal to find the right element again. A combined lookup and remove would have cleaned up the code a bit but for sure, but just with just the removal I don't see the point.
e7dab7f to
39198c4
Compare
|
Changes:
|
39198c4 to
5b3c5c7
Compare
|
Changes:
|
| inflight_set::iterator i = m_inflight.find(transfer); | ||
| if (i == m_inflight.end()) { // not found | ||
| OLA_WARN << "Mismatched libusb transfer: " | ||
| << transfer << " not in inflight set"; | ||
| return; | ||
| } | ||
|
|
||
| m_inflight.erase(i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies, wrong command, after looking more carefully ola::STLRemove will do what you want:
http://docs.openlighting.org/ola/doc/latest/group__stl.html#ga6bab5568a6d6ef14d4faccea9eddd41b
Or is there a risk of multiple equal transfers in the set (I assume they have a unique ID, but maybe not)?
peternewman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still can't get use to C++'s pop not being like this:
https://perldoc.perl.org/functions/pop
A few more, mostly minor, comments.
5b3c5c7 to
6147c2e
Compare
Currently we only use a single active transfer for both sending and
reveiving usb packets.
This is suboptimal in terms of latency, USB actually guarantees certain
turnaround times for interrupt transfers for example but that only really
works if there is always an IRP ready to go in the USB host controller.
According to my measurments interrupt transfers with bInterval=1 can be
delayed by some tens of milliseconds instead of happening evey millisecond
on the dot if there are periods with no transfers ready to go.
In order to support multiple transfers being inflight I replace the
transfer state machinery in AsyncUsbTransceiverBase with a set of inflight
transfers and a queue of idle transfers.
The bookkeeping happens in a new TransferCompleteInternal method which
wraps the TransferComplete() method provided by subclasses. This split also
allowed moving some duplicated logic for LIBUSB_TRANSFER_NO_DEVICE to the
superclass.
The number of transfers to allow is passed to AsyncUsb{Sender,Receiver} as
a constructor argument since supporting more than one needs some
cooperation from the derived classes. Currently everything just defaults to
one transfer which shouldn't change the behaviour one bit.
6147c2e to
8255115
Compare
In developing a custom USB->DMX widget for OLA I've noticed that packet latency isn't as consistent as possible when only using a single libusb transfer at a time. Hence here I add support for more than one and also fix a nasty use after free hazard while I'm at it.
Commit messages copied below:
usbdmx: Add support for having multiple inflight transfersCurrently we only use a single active transfer for both sending and
reveiving usb packets.
This is suboptimal in terms of latency, USB actually guarantees certain
turnaround times for interrupt transfers for example but that only really
works if there is always an IRP ready to go in the USB host controller.
According to my measurments interrupt transfers with bInterval=1 can be
delayed by some tens of milliseconds instead of happening evey millisecond
on the dot if there are periods with no transfers ready to go.
In order to support multiple transfers being inflight I replace the
transfer state machinery in AsyncUsbTransceiverBase with a set of inflight
transfers and a queue of idle transfers.
The bookkeeping happens in a new TransferCompleteInternal method which
wraps the TransferComplete() method provided by subclasses. This split also
allowed moving some duplicated logic for LIBUSB_TRANSFER_NO_DEVICE to the
superclass.
The number of transfers to allow is passed to AsyncUsb{Sender,Receiver} as
a constructor argument since supporting more than one needs some
cooperation from the derived classes. Currently everything just defaults to
one transfer which shouldn't change the behaviour one bit.
usbdmx: Remove redundant CancelTransfer() calls:The superclass destructor already calls CancelTransfer, no need to do it in
the derived classes also. To prevent this in the future this also make
CancelTransfer private.
usbdmx: Fix use after free hazard in destructor(see diff for commentary)