book icon indicating copy to clipboard operation
book copied to clipboard

Wrong concept in subsection "Building Our Own Async Abstractions" of section "17.3 Working with Any Number of Futures"

Open rusty-bytes opened this issue 7 months ago • 0 comments
trafficstars

In subsection "Building Our Own Async Abstractions" of section "17.3 Working with Any Number of Futures" (link: https://doc.rust-lang.org/book/ch17-03-more-futures.html#building-our-own-async-abstractions),

the concept in paragraph

"We also know that race is not fair, polling arguments in the order in which they are passed. Thus, we pass future_to_try to race first so it gets a chance to complete even if max_time is a very short duration. If future_to_try finishes first, race will return Left with the output from future_to_try. If timer finishes first, race will return Right with the timer’s output of ()."

appears not to be correct.

future_to_try gets a chance to complete in any case, even if max_time is a very short duration. In fact whatever the value for max_time, the trpl::sleep() future would be suspended as soon as invoked, and then future_to_try would be started in any case and so get a chance to complete. Actually passing trpl::sleep() as the first parameter to trpl::race() seems to be more correct, as illustrated in the following example:

max_time = 2 secs future_to_try computes for 5 secs (e.g. thread::sleep(Duration::from_secs(5))), then awaits for other 5 secs (e.g. trpl::sleep(Duration::from_secs(5)).await), and then terminates

  • Behaviour 1: passing future_to_try as the first parameter to trpl::race()

    • Outcome:
      • future_to_try is started
      • future_to_try computes for 5 secs
      • future_to_try is suspended because of its await
      • trpl::sleep(max_time) is started
      • trpl::sleep(max_time) is immediately suspended because of its await
      • future_to_try is resumed
      • future_to_try is immediately suspended because of its await
      • trpl::sleep(max_time) is resumed after 2 secs
      • trpl::sleep(max_time) terminates immediately because it has already awaited for 2 secs
      • timeout() returns after 7 secs with an Err()
  • Behaviour 2: passing trpl::sleep() as the first parameter to trpl::race()

    • Outcome:
      • trpl::sleep(max_time) is started
      • trpl::sleep(max_time) is immediately suspended because of its await
      • future_to_try is started
      • future_to_try computes for 5 secs
      • future_to_try is suspended because of its await
      • trpl::sleep(max_time) is resumed
      • trpl::sleep(max_time) terminates immediately because it has already awaited for more than 2 secs
      • timeout() returns after 5 secs with an Err()

Behaviour 1 times out after 7 secs while behaviour 2 times out after 5 secs, so behaviour 2 seems to be more correct.

rusty-bytes avatar Apr 09 '25 14:04 rusty-bytes