Skip to content

fix FuturesOrdered#2664

Merged
taiki-e merged 1 commit into
rust-lang:masterfrom
conradludgate:fix-ordered
Jan 15, 2023
Merged

fix FuturesOrdered#2664
taiki-e merged 1 commit into
rust-lang:masterfrom
conradludgate:fix-ordered

Conversation

@conradludgate

@conradludgate conradludgate commented Nov 12, 2022

Copy link
Copy Markdown
Contributor

fixes #2663

@conradludgate conradludgate changed the title fix FuturesOrdered #2663 fix FuturesOrdered Nov 12, 2022
@taiki-e

taiki-e commented Nov 20, 2022

Copy link
Copy Markdown
Member

Thanks for the PR! Considering the overflow of isize (which can actually happen on 32-bit targets), this still seems broken, but this seems more correct than the current one.

@conradludgate

conradludgate commented Nov 20, 2022

Copy link
Copy Markdown
Contributor Author

Yeah. I have some ideas how to fix the overflow too, but it's not as trivial a fix

https://github.com/conradludgate/futures-buffered/blob/7db2b4ca822ee95bb53871fee7867b420a04a7fa/src/futures_ordered_bounded.rs#L216-L231

Essentially, if the next_outgoing_index has the MSB set, then it flips the MSB of every task/output. This preserves the order and ensures that the outgoing is <= isize::MAX. The length of the queue would have to be another isize::MAX+1 in order to overflow, but you'd OOM before that.

Reason this is correct Let's say our system is 16-bit. So we can have a theoretical maximum memory of 65536 bytes. Our futures are `[(usize, F)]` which is at least 2 bytes assuming ZST future. Our ready queue similarly stores `[(usize, F::Output)]` which is also at least 2 bytes with a ZST output.

In total, we can only fit 65536/2 entries into memory, ignoring any extra necessary overhead. Therefore, we only need to be able to store at maximum (usize::MAX+1)/2 entries.

In our FuturesOrdered, we have next_outgoing_index as the head, and next_incoming_index as the tail.

[_, _, .., _, _, _, _, _, .., _, _]
           ^ head.     ^ tail

If our head gets over half way through our usize, then to store our theoretical maximum, tail can be at most usize::MAX+1, which is 0. We can't insert any more without OOM as shown, so this index is never read or compared against.

Since all other indices must be head <= x < tail, then we know that they all have the MSB set, so flipping the MSB will be the same as x - (usize::MAX+1)/2 which must preserve the order of the queues.

It should be possible to implement here too, but it might not be super efficient with the task linked list

@taiki-e taiki-e merged commit 54e07b8 into rust-lang:master Jan 15, 2023
@taiki-e taiki-e added A-stream Area: futures::stream 0.3-backport: pending The maintainer accepted to backport this to the 0.3 branch, but backport has not been done yet. labels Jan 15, 2023
@taiki-e

taiki-e commented Jan 15, 2023

Copy link
Copy Markdown
Member

Thanks! Opened #2689 to track overflow issue.

@taiki-e taiki-e added 0.3-backport: completed and removed 0.3-backport: pending The maintainer accepted to backport this to the 0.3 branch, but backport has not been done yet. labels Jan 30, 2023
taiki-e pushed a commit that referenced this pull request Jan 30, 2023
@taiki-e taiki-e mentioned this pull request Jan 30, 2023
taiki-e pushed a commit that referenced this pull request Jan 30, 2023
crapStone pushed a commit to Calciumdibromid/CaBr2 that referenced this pull request Feb 2, 2023
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [futures](https://rust-lang.github.io/futures-rs) ([source](https://github.com/rust-lang/futures-rs)) | dependencies | patch | `0.3.25` -> `0.3.26` |

---

### Release Notes

<details>
<summary>rust-lang/futures-rs</summary>

### [`v0.3.26`](https://github.com/rust-lang/futures-rs/blob/HEAD/CHANGELOG.md#&#8203;0326---2023-01-30)

[Compare Source](rust-lang/futures-rs@0.3.25...0.3.26)

-   Add `Either::as_pin_mut` and `Either::as_pin_ref` ([#&#8203;2691](rust-lang/futures-rs#2691))
-   Add `Shared::ptr_eq` and `Shared::ptr_hash` ([#&#8203;2691](rust-lang/futures-rs#2691))
-   Implement `FusedStream` for `Buffered` ([#&#8203;2676](rust-lang/futures-rs#2676))
-   Implement `FusedStream` for all streams in `ReadyChunks` ([#&#8203;2693](rust-lang/futures-rs#2693))
-   Fix bug in `FuturesOrdered::push_front` ([#&#8203;2664](rust-lang/futures-rs#2664))
-   Remove `Fut::Output: Clone` bounds from some `Shared` methods ([#&#8203;2662](rust-lang/futures-rs#2662))
-   Remove `T: Debug` bounds from `Debug` implementations of `mpsc` and `oneshot` types ([#&#8203;2666](rust-lang/futures-rs#2666), [#&#8203;2667](rust-lang/futures-rs#2667))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4xMTYuMSIsInVwZGF0ZWRJblZlciI6IjM0LjExOS4yIn0=-->

Co-authored-by: cabr2-bot <cabr2.help@gmail.com>
Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1762
Reviewed-by: crapStone <crapstone@noreply.codeberg.org>
Co-authored-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Co-committed-by: Calciumdibromid Bot <cabr2_bot@noreply.codeberg.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FuturesOrdered push_front does not work at the start

2 participants