Skip to content

Use std::chrono based functions #13046

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

Merged
merged 2 commits into from
Jun 18, 2020
Merged

Conversation

hugueskamba
Copy link
Collaborator

@hugueskamba hugueskamba commented May 30, 2020

Summary of changes

The chrono based functions improve readability. Using them also removes
warnings related to usage of deprecated APIs.

Impact of changes

Removes build warnings related to usage of deprecated time related functions.

Migration actions required

n/a

Documentation

n/a


Pull request type

[X] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

[] No Tests required for this change (E.g docs only update)
[X] Covered by existing mbed-os tests (Greentea or Unittest)
[] Tests / results supplied as part of this PR

Reviewers

@kjbracey-arm


@mergify mergify bot added the needs: work label May 30, 2020
@ciarmcom ciarmcom requested review from kjbracey and a team May 30, 2020 21:00
@ciarmcom
Copy link
Member

@hugueskamba, thank you for your changes.
@kjbracey-arm @ARMmbed/mbed-os-pan @ARMmbed/mbed-os-wan @ARMmbed/mbed-os-maintainers @ARMmbed/mbed-os-storage @ARMmbed/mbed-os-ipcore @ARMmbed/mbed-os-core please review.

@hugueskamba hugueskamba force-pushed the hk_use_chrono branch 2 times, most recently from f567894 to 043268d Compare May 31, 2020 18:53
Copy link
Contributor

@kjbracey kjbracey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Various comments - some of them apply to multiple changes.

This is very much a "bare minimum" Chrono "conversion". Silencing the warnings, but not really following through, and leaving absolutely all touched code using integers as much as possible.

There is a question of how far you can go, when you're potentially touching a lot of code, and maybe that code is not Mbed-specific, but this is clearly erring too far on the "don't touch anything, and cast at the last minute" side.

Certainly having a define for SOCKET_TIMEOUT as (1 * 1000) and then having C++ code using it as microseconds(SOCKET_TIMEOUT) makes no sense. Define it as 1ms in the first place.

(Namespace pollution limitations would force that to be std::chrono::milliseconds(1) if in a header, but you can still not be an integer).

Start with the easy ones, then we can see if it's worth doing a fuller conversion on, say, the RfPhys.

To some extent the reason they were left is because I could see they needed a fuller converison, and just didn't get around to it. I've not left the "easy" ones :)

@@ -189,7 +192,7 @@ static TestPins *test_pins;

static uint32_t rf_get_timestamp(void)
Copy link
Contributor

@kjbracey kjbracey Jun 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're doing a Chrono conversion, it's usually better to make an effort to pass it through the codebase as much as you can. If all you do is convert at the last moment for the APIs, but keep all your own code using integers, then you're not really following through, or doing much to catch errors.

This code should be using HighResClock::time_points for its timestamps, and using HighResClock::now() to get the time.

It's currently using a Timer, but that's no longer the best tool. It doesn't want a stopwatch - it's not stopping and starting it - it wants a high-res monotonic clock. The only previous way to get that was a Timer, but now there is HighResClock. Just remember to do HighResClock::lock() where the Timer::start() currently is.

As it's currently engineered for 32-bit calculations, and seems to cope okay with them, you could maintain that by using a 32-bit version of

using microseconds_u32_t = std::chrono::duration<uint32_t, std::micro>;
using rf_timestamp_u32_t = std::chrono::time_point<HighResClock::time_point::clock, microseconds_u32_t>;

Then

static rf_timestamp_u32_t rf_get_timestamp(void)
{
    return HighResClock::now();
}

if (tx_time != tx_time.min()) {
    microseconds_u32_t backoff_time = tx_time - rf_get_timestamp();
    // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately
    if (backoff_time <= 65ms) {
        rf->cca_timer.attach(rf_csma_ca_timer_signal, backoff_time);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a bit more involved. I have reverted the changes.

mbed::callback(this, &GenericGap::on_advertising_timeout),
durationCast<millisecond_t>(maxDuration).value()
std::chrono::microseconds(durationCast<millisecond_t>(maxDuration).value())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hang on, this is a code-base with its own Chrono-like duration handling stuff. Either convert and replace that, or add some conversion operators. Absolutely no need to be doing this mess manually at usage sites. The usage site could look like:

_advertising_timeout.attach(
            mbed::callback(this, &GenericGap::on_advertising_timeout),
            maxDuration)

Adding user-defined conversion operators to Duration seems simplest. I think this is it:

operator std::chrono::duration<Rep, std::ratio<TB, 1000000>::type>() const
{
    return std::chrono::duration<Rep, std::ratio<TB, 1000000>::type>{duration};
}

I note that this original code is actually wrong, and the minimal Chrono conversion didn't spot it - it's passing milliseconds to microseconds, and you've faithfully reproduced the error. A correct Duration->std::chrono::duration conversion will clear it up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Durations are a strange things in BLE, we have many different units which are not based on ms and its multiple adding an interface where you can convert to and from was natural.

Replacing it with chrono may help us in solving the problem. We just have to think of Ann efficient way of solving the boundary issue.

Thanks for spotting the issue, this is on the legacy compatibility path, we missed it.

Copy link
Contributor

@kjbracey kjbracey Jun 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New suggestion - a simple non-conversion-operator method:

auto Duration::valueChrono() const
{
    return std::chrono::duration<Rep, typename std::ratio<TB, 1000000>::type>{duration};
}

@pan- I saw your suggestion with the handling of "forever". Seems like overkill, with runtime cost? Can't really assume a Chrono user would treat max() as forever, and if there was special handling of some other "forever" value of the representation, they could check for it explicitly. The conversion maintains representation, so that's possible.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reverted the section that require more complex changes for an elegant solution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that the chrono types do not inherently have those semantics, again for any value. If you want those semantics, then you need to code them - I don't how coercing "forever value, whatever it may be" into "max" is better than preserving the forever value and assuming the same semantics. If you convert a type with "forever = 0" into chrono, then that value means forever if its value is 0.

I see that using "max" may make it not fail so badly when you forget to put the special "forever" handling in for the chrono section, but any conversion that doesn't put the special handling in is wrong. This is covering up a programming error, and with a runtime cost.

Yes, I think it would make sense to assert on a forever conversion. That should actually lead to no code, assuming it forces you to write

if (myDuration.is_forever()) {
     myChrono = myChronoForever;
} else {
     myChrono = myDuration.chronoValue();
}

The assert inside the chronoValue shouldn't generate code, because it can see that the condition is already cleared by the if it's inside. And if the forever representations match, even the if should vanish? Making it a direct assignment. Pretty certain it should.

Are you happy with the naming?

Copy link
Member

@pan- pan- Jun 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely agree that less damaging doesn't mean its not wrong. The assertion seems to be the thing to do. If an is_forever member function is added it should be named isForever to keep the code consistent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't asking about the naming of my code snippet - that was just me guessing that you already had an is_forever or something. Surely you do. And chronoValue was my misremembering of my original valueChrono suggestion.

I was repeating my earlier question about the name getChronoDuration as it currently stands. Doesn't seem to fit to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valueChrono is a good replacement for getChronoDuration.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kjbracey-arm @pan-
Could you please review this?
Thanks.

@mergify mergify bot removed the needs: review label Jun 1, 2020
@mergify mergify bot dismissed kjbracey’s stale review June 1, 2020 17:31

Pull request has been modified.

@hugueskamba hugueskamba force-pushed the hk_use_chrono branch 3 times, most recently from 0c67640 to 88ef9b0 Compare June 1, 2020 17:45
@hugueskamba hugueskamba force-pushed the hk_use_chrono branch 3 times, most recently from 63b3290 to 2f9feae Compare June 3, 2020 13:12
@adbridge
Copy link
Contributor

@pan- could you review please?

@adbridge adbridge added the release-type: patch Indentifies a PR as containing just a patch label Jun 11, 2020
@mergify mergify bot removed the needs: CI label Jun 17, 2020
@mbed-ci
Copy link

mbed-ci commented Jun 17, 2020

Test run: FAILED

Summary: 2 of 3 test jobs failed
Build number : 1
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_build-ARM
  • jenkins-ci/mbed-os-ci_build-GCC_ARM

@mergify mergify bot added needs: CI and removed needs: work labels Jun 17, 2020
@0xc0170
Copy link
Contributor

0xc0170 commented Jun 18, 2020

The failures are related, please review

@mergify mergify bot dismissed kjbracey’s stale review June 18, 2020 14:26

Pull request has been modified.

@hugueskamba
Copy link
Collaborator Author

The failures are related, please review

The following commit addresses the failure in the tests-netsocket-udp test:
c79a065

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 18, 2020

CI started

@mbed-ci
Copy link

mbed-ci commented Jun 18, 2020

Test run: FAILED

Summary: 2 of 3 test jobs failed
Build number : 2
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_build-ARM
  • jenkins-ci/mbed-os-ci_build-GCC_ARM

@hugueskamba
Copy link
Collaborator Author

This force-push should fix this failure.

@hugueskamba
Copy link
Collaborator Author

hugueskamba commented Jun 18, 2020

CI re-started

@mbed-ci
Copy link

mbed-ci commented Jun 18, 2020

Test run: FAILED

Summary: 2 of 3 test jobs failed
Build number : 3
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_build-ARM
  • jenkins-ci/mbed-os-ci_build-GCC_ARM

Use std::chrono literals and variables where it makes sense
@hugueskamba
Copy link
Collaborator Author

This force-push should fix this failure.

@hugueskamba
Copy link
Collaborator Author

CI restarted.

@mbed-ci
Copy link

mbed-ci commented Jun 18, 2020

Test run: SUCCESS

Summary: 7 of 7 test jobs passed
Build number : 4
Build artifacts

@0xc0170 0xc0170 merged commit 3e42991 into ARMmbed:master Jun 18, 2020
@mergify mergify bot removed the ready for merge label Jun 18, 2020
@hugueskamba hugueskamba deleted the hk_use_chrono branch June 18, 2020 20:45
@adbridge adbridge added release-version: 6.1.0 Release-pending and removed release-type: patch Indentifies a PR as containing just a patch Release-pending labels Jun 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants