Skip to content

Conversation

@Lucretiel
Copy link
Contributor

@Lucretiel Lucretiel commented Apr 2, 2020

This pull request adds first, first_all, and first_ok. These are selection functions, similar to the existing select and friends, which (unlike select) don't return the incomplete futures after finishing (simply discards them instead). This allows them to have implementations that are simpler, have less overhead, and do not require Unpin on their contents.

This pull request is in progress:

Fixes #2031 and #2110

- Removed FusedIterator; .fuse() is equivalent. - FirstOk is more explicit about its use of FusedIterator. - This design will have to wait for rust-lang#2111 to be resolved; currently the contract of FusedFuture is not strict enough for our needs.
@Lucretiel
Copy link
Contributor Author

The remaining test failures seem unrelated to these changes

@cramertj
Copy link
Member

This looks good to me, though the dependence on #2111 worries me because I don't feel like I have a good handle on the best way to resolve that tension. Thanks for all your hard work here, though-- these combinators do look conveniently simpler.

Copy link
Member

@taiki-e taiki-e left a comment

Choose a reason for hiding this comment

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

Sorry for the delay reviewing. I have a few suggestions, but this looks good overall.

Comment on lines +18 to +19
unsafe_pinned!(future1: F1);
unsafe_pinned!(future2: F2);
Copy link
Member

Choose a reason for hiding this comment

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

Please use pin_project instead of pin_utils::unsafe_pinned. (Since #2128, we have been using it.)

pub struct FirstAll<F> {
// Critical safety invariant: after FirstAll is created, this vector can
// never be reallocated, in order to ensure that Pin is upheld.
futures: Vec<F>,
Copy link
Member

Choose a reason for hiding this comment

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

I recommend to use Pin<Box<[F]>> + this helper function, instead of Vec<F> + Pin::new_unchecked

// Critical safety invariant: after FirstAll is created, this vector can
// never be reallocated, nor can its contents be moved, in order to ensure
// that Pin is upheld.
futures: Vec<F>,
Copy link
Member

Choose a reason for hiding this comment

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

Same here


impl<T, E, F> Future for FirstOk<F>
where
F: Future<Output = Result<T, E>> + FusedFuture,
Copy link
Member

Choose a reason for hiding this comment

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

I recommend to use Fuse instead of relying on FusedFuture, as I said in #2111.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I considered this, and if we remove FusedFuture entirely (like you suggested) then we can go this route, but I went with the trait here because many futures are "inherently" fused, so in the interest of zero-cost abstractions I thought it made more sense to just have the user call .fuse() only if they need to

Copy link
Member

@taiki-e taiki-e Oct 14, 2020

Choose a reason for hiding this comment

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

so in the interest of zero-cost abstractions I thought it made more sense to just have the user call .fuse() only if they need to

Patterns like newtype are certainly not zero-cost, but Fuse just adds a flag to indicate if the future is complete and I think the actual cost is very small.

Another reason I don't want to add new features that rely on Fused* traits is that they are very likely to be removed in the next major version. (see #2207)
Even if we add features that rely on Fused* traits, they will be changed to use Fuse or MaybeDone. And if users forget to remove .fuse() on update to new version, it will eventually be even more inefficient.

@taiki-e taiki-e added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author label Nov 3, 2020
@taiki-e taiki-e added A-future Area: futures::future and removed futures-util labels Dec 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-future Area: futures::future S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author

3 participants