-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Timespec refactor (again) #45
Timespec refactor (again) #45
Conversation
@@ -551,41 +542,25 @@ | |||
} | |||
fd_set writefds; | |||
size_t bytes_written = 0; | |||
struct timeval timeout; | |||
timeout.tv_sec = timeout_.write_timeout_constant / 1000; | |||
timeout.tv_usec = static_cast<int> (timeout_.write_timeout_multiplier % 1000); |
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 don't understand what this logic is. My implementation below attempts to do what I believe is correct behaviour rather than follow this.
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.
timeout_.write_timeout_multiplier % 1000
is the remainder of milliseconds which is left over from removing the seconds. Then the next line multiplies it by 1000 to get it into microseconds.
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.
If that's the case, shouldn't it be write_timeout_constant in both lines, rather than write_timeout_multiplier in the second?
AFAICT, it should be write_timeout_constant + (write_timeout_multiplier * expected_bytes), with that resulting milliseconds value then converted to timeval via the div/mod procedure. In any case, that's what the proposed replacement logic does.
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.
Yes, that was likely a typo...
Sorry this is taking so long for me to review, I have been getting distracted, and I want to make a sold few passes over this since it is such a substantial change. Hopefully I can complete my feedback tonight sometime. |
No worries; I appreciate the thoroughness! |
Okay, I've remove the modulus operator and the exception logic. EDIT: Looks like that timeout logic isn't quite right yet—I'm seeing some weird negative timespec issues. |
That should do it. |
Looks good to me, I opened a pull request against your pull request branch to use |
Looks like this pull request needs a rebase. |
C-style casting can result in undesired reinterpret_casts So we should avoid them, see: http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used
Done. |
Thanks @mikepurvis. Ok, this looks ready to me. I want to get some more eyes on it though. @ashgti @dirk-thomas @davidhodo Can I get some code review? Here is a brief summary of this change set:
|
int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6); | ||
if (tv_nsec > 1e9) { | ||
int64_t sec_diff = tv_nsec / static_cast<int> (1e6); | ||
expiry.tv_nsec = tv_nsec - static_cast<int> (1e6 * sec_diff); |
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.
The condition with 1e9 but the math operations with 1e6 look bogus to me.
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 agree with @dirk-thomas I think those should be 1e9
because we are going from nanoseconds to seconds 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.
Whoops—and it was the wrong number even in the original modulo logic. Fixed now.
Just to check back in here, I've been using this code consistently for the past week with device drivers on Grizzly, and it seems to be working as expected—I'm not seriously exercising the timing/timeout logic, but given the bugs in the present implementation, I'm not sure anyone else is either. The real solution to verifying it is #47, but I'm hoping we can merge this in advance of that being done. |
@mikepurvis Sorry about that, I have been busy, I'll revisit this asap. |
Regardless of comprehensive tests and portable tests for the actual end-to-end serial behavior, I think the MillisecondTimer class is easily unit tested in a portable fashion. I would like to see some basic unit tests for this class, as they would have likely caught both @dirk-thomas's comments as well as my most recent one about the conditional logic. |
Sure. Part of the idea of creating the class was to make a testable unit. Where would you like the tests to be, and how should their building and execution be handled? |
I would put them in the |
Sorry the |
… test builds into separate makefile.
Alright, have added some simple tests for MillisecondTimer—unfortunately, not perfectly deterministic, so there will be spurious failures. Ideal would be to somehow bubble up more information about the failed tests, to see if they represent actual corner cases or just flukes. Have also adding test running to travis, with the proviso that test failures do not fail the build. I can't see an easy way to do this, as it appears that the catkin test make targets return zero pretty much no matter what. I believe you'd need to throw in a Perl or Python one-liner to actually check the result XMLs for |
Looks good to me. |
Thanks for the review and merge! |
Thanks for the contribution. |
A simpler, gentler take on what was previously discussed in #42 and #43.