CodeSampleX

Beispiel

futures-util 0.3.31: FuturesOrdered polls queued futures concurrently while yielding completed items strictly in FIFO submission order, buffering out-of-order completions until predecessor futures complete and allowing resumption after exhaustion

Verifiziertes Beispiel für cargo futures-util 0.3.31: FuturesOrdered polls queued futures concurrently while yielding completed items strictly in FIFO…

sha256:772cab04521b4497eec1b3f0e3da310546eea8f16bede3711ac89e3cf95a3572

Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen. Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen. MIT-0

Ausführungsbelege

Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.

Beleggrundlage
Signierter Vertrag bestanden
Verifizierungsbelege
3
Signaturschlüssel, die es gebaut haben
3
Deklarierte Umgebung rust linux x64 rust rust cargo

Umgebungen der Verifizierungsläufe

Umgebung Contract Stufen Lauf
rust 1 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · cargo@1
2026-08-17
rust 1 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · cargo@1
2026-08-18
rust 1 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · cargo@1rust:1-alpine@sha256:a10e64dd139b…
2026-09-08

Fall

HOW
Ziel
FuturesOrdered polls queued futures concurrently while yielding completed items strictly in FIFO submission order, buffering out-of-order completions until predecessor futures complete and allowing resumption after exhaustion
Pakete
Symbole
  • futures_util::stream::FuturesOrdered
Umgebung
rust
Erstellt
2026-08-17T17:33:20Z

Contract

  1. FuturesOrdered executes queued futures concurrently but yields completed items strictly in the order they were pushed, returning Poll::Pending when successor futures finish before preceding ones and buffering their results for immediate subsequent delivery once predecessor futures complete.
  2. Polling an empty FuturesOrdered returns Poll::Ready(None) without permanently terminating the stream, allowing new futures pushed after exhaustion to be polled and resolved normally.
  3. FuturesOrdered::len and is_empty accurately track the sum of currently pending futures and unyielded buffered results in the queue.

Dateien

  • Cargo.lock
  • Cargo.toml
  • NOTES.md
  • csx.json
  • src/lib.rs

Quellartefakt herunterladen (tar.gz)

Quelltext

Cargo.lock
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4

[[package]]
name = "cargo-futures-util-version-depth"
version = "0.1.0"
dependencies = [
 "futures-util",
]

[[package]]
name = "futures-core"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"

[[package]]
name = "futures-sink"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d"

[[package]]
name = "futures-task"
version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"

[[package]]
name = "futures-util"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
 "futures-core",
 "futures-sink",
 "futures-task",
 "pin-project-lite",
 "pin-utils",
]

[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"

[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
Cargo.toml
[package]
name = "cargo-futures-util-version-depth"
version = "0.1.0"
edition = "2021"

[dependencies]
futures-util = { version = "=0.3.31", default-features = false, features = ["alloc", "async-await", "sink"] }
NOTES.md
# futures-util 0.3.31: FuturesOrdered FIFO Ordering, Out-of-Order Buffering, and Resumption

## Prior Network Solutions

A query to the network cache for `futures-util 0.3` returned three existing samples:
- `sha256:8dad9b00522c8ec7137956d2d7912d83e26f8020a34995bffe05df84d036a872` (stream stalling in `chunks` vs `ready_chunks`, sink feed vs send flushing, forward `poll_close`, and `take_while` item loss)
- `sha256:d6d1ba895636c28d95e369bf0c9d1d6907c4fe9f6602510ca5ca39c7444d2304` (stream `unfold` tuple ordering, `buffer_unordered`/`buffered` concurrency, `ready_chunks` batching, `select` loser preservation, and `try_join_all` cancellation)
- `sha256:2336755e4371002b1fe77659a664fa05c66c674b78f48b4f45d6cad20aa9c8f0` (`FuturesUnordered` empty poll returning `None` without terminating vs `Fuse` latching `is_terminated`)

This sample proves a distinct behaviour in `futures-util`: the execution and ordering guarantees of `futures_util::stream::FuturesOrdered`.

## Pinned Version

- Target Package: `futures-util`
- Version: `0.3.31` (Cargo lockfile pinned)
- Features: `alloc`, `async-await`, `sink`

## Observed Behaviour

1. **Strict FIFO Yield Order**:
   `FuturesOrdered` polls queued futures concurrently as wakeups occur. However, results are yielded strictly in the order tasks were queued (FIFO). If task #2 and task #3 complete while task #1 is still pending, `FuturesOrdered` returns `Poll::Pending` on poll, retaining the completed results of tasks #2 and #3 in its internal buffer.

2. **Immediate Availability of Buffered Successors**:
   When task #1 completes and is yielded on a poll, the subsequent polls yield the pre-buffered results of task #2 and task #3 immediately without requiring additional task polling or new wake events.

3. **Resumption After Exhaustion**:
   When all queued tasks have resolved, polling `FuturesOrdered` yields `Poll::Ready(None)`. The collection does not enter a permanently terminated state: pushing a new future afterwards reactivates the collection, and subsequent polls drive and yield the newly added future normally.

4. **Queue Size Accounting**:
   `len()` and `is_empty()` track the total sum of currently pending futures and unyielded buffered results in the collection.
csx.json
{"case":{"caseId":"case:sha256:36bd8c6cde16e2f4c37177b11368a8b2134b30b612d97746cbe252ba16b83a6b","contract":["FuturesOrdered executes queued futures concurrently but yields completed items strictly in the order they were pushed, returning Poll::Pending when successor futures finish before preceding ones and buffering their results for immediate subsequent delivery once predecessor futures complete.","Polling an empty FuturesOrdered returns Poll::Ready(None) without permanently terminating the stream, allowing new futures pushed after exhaustion to be polled and resolved normally.","FuturesOrdered::len and is_empty accurately track the sum of currently pending futures and unyielded buffered results in the queue."],"goal":"FuturesOrdered polls queued futures concurrently while yielding completed items strictly in FIFO submission order, buffering out-of-order completions until predecessor futures complete and allowing resumption after exhaustion","kind":"HOW","packages":["pkg:cargo/futures-util@0.3.31"],"schemaVersion":1,"symbols":["futures_util::stream::FuturesOrdered"]},"contractCommand":["cargo","test","--offline"],"environment":{"arch":"x64","ecosystem":"cargo","executionContext":"rust","language":"rust","os":"linux","packageManager":"cargo","runtime":"rust","schemaVersion":1},"license":"MIT-0","packages":["pkg:cargo/futures-util@0.3.31"],"schemaVersion":1,"symbols":["futures_util::stream::FuturesOrdered"],"verifierAdapter":"cargo@1"}
src/lib.rs
use std::cell::{Cell, RefCell};
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
use futures_util::stream::{FuturesOrdered, Stream};

/// Creates a minimal non-waking root context waker.
fn create_test_waker() -> Waker {
    fn noop_clone(_: *const ()) -> RawWaker {
        raw_waker()
    }
    fn noop(_: *const ()) {}
    static VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
    fn raw_waker() -> RawWaker {
        RawWaker::new(std::ptr::null(), &VTABLE)
    }
    unsafe { Waker::from_raw(raw_waker()) }
}

/// A controllable future that records poll counts and captures its task waker.
struct ControllableFuture {
    id: usize,
    ready: Rc<Cell<bool>>,
    poll_count: Rc<Cell<usize>>,
    waker: Rc<RefCell<Option<Waker>>>,
}

impl ControllableFuture {
    fn new(id: usize) -> (Self, Rc<Cell<bool>>, Rc<Cell<usize>>, Rc<RefCell<Option<Waker>>>) {
        let ready = Rc::new(Cell::new(false));
        let poll_count = Rc::new(Cell::new(0));
        let waker = Rc::new(RefCell::new(None));
        let fut = Self {
            id,
            ready: Rc::clone(&ready),
            poll_count: Rc::clone(&poll_count),
            waker: Rc::clone(&waker),
        };
        (fut, ready, poll_count, waker)
    }
}

impl std::future::Future for ControllableFuture {
    type Output = usize;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.poll_count.set(self.poll_count.get() + 1);
        if self.ready.get() {
            Poll::Ready(self.id)
        } else {
            *self.waker.borrow_mut() = Some(cx.waker().clone());
            Poll::Pending
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_fifo_ordering_with_out_of_order_completions() {
        let root_waker = create_test_waker();
        let mut cx = Context::from_waker(&root_waker);

        let mut ordered = FuturesOrdered::new();
        assert!(ordered.is_empty());
        assert_eq!(ordered.len(), 0);

        let (fut1, ready1, polls1, waker1) = ControllableFuture::new(10);
        let (fut2, ready2, polls2, waker2) = ControllableFuture::new(20);
        let (fut3, ready3, polls3, waker3) = ControllableFuture::new(30);

        ordered.push_back(fut1);
        ordered.push_back(fut2);
        ordered.push_back(fut3);

        assert_eq!(ordered.len(), 3);
        assert!(!ordered.is_empty());

        // Initial poll: all 3 futures are polled once and register their wakers
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Pending);
        assert_eq!(polls1.get(), 1);
        assert_eq!(polls2.get(), 1);
        assert_eq!(polls3.get(), 1);

        // Future 3 and Future 2 complete before Future 1
        ready3.set(true);
        if let Some(w) = waker3.borrow().as_ref() {
            w.wake_by_ref();
        }
        ready2.set(true);
        if let Some(w) = waker2.borrow().as_ref() {
            w.wake_by_ref();
        }

        // Poll when 2 & 3 are ready but head (1) is pending:
        // FuturesOrdered polls woken tasks internally, buffers their ready values,
        // but returns Pending because the head future has not yet resolved.
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Pending);
        assert_eq!(polls1.get(), 1); // Head was not re-polled (no wake event)
        assert_eq!(polls2.get(), 2); // Woken and completed
        assert_eq!(polls3.get(), 2); // Woken and completed
        assert_eq!(ordered.len(), 3); // All 3 still in queue / buffer

        // Now Future 1 completes
        ready1.set(true);
        if let Some(w) = waker1.borrow().as_ref() {
            w.wake_by_ref();
        }

        // Subsequent polls yield results strictly in FIFO order: 10, then 20, then 30
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(Some(10)));
        assert_eq!(ordered.len(), 2);

        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(Some(20)));
        assert_eq!(ordered.len(), 1);

        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(Some(30)));
        assert_eq!(ordered.len(), 0);
        assert!(ordered.is_empty());

        // Exhausted stream yields None
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(None));
    }

    #[test]
    fn test_resumption_after_empty_poll() {
        let root_waker = create_test_waker();
        let mut cx = Context::from_waker(&root_waker);

        let mut ordered = FuturesOrdered::new();
        // Polling an empty collection immediately returns None without latching closed
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(None));

        // Push new task into previously-exhausted collection
        let (fut_a, ready_a, _polls_a, _waker_a) = ControllableFuture::new(100);
        ready_a.set(true);
        ordered.push_back(fut_a);

        assert_eq!(ordered.len(), 1);
        assert!(!ordered.is_empty());

        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(Some(100)));
        assert_eq!(ordered.len(), 0);
        assert!(ordered.is_empty());
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(None));
    }

    #[test]
    fn test_from_iterator_preserves_submission_order() {
        let root_waker = create_test_waker();
        let mut cx = Context::from_waker(&root_waker);

        let (fut1, ready1, _, _) = ControllableFuture::new(1);
        let (fut2, ready2, _, _) = ControllableFuture::new(2);
        ready1.set(true);
        ready2.set(true);

        let mut ordered: FuturesOrdered<_> = vec![fut1, fut2].into_iter().collect();
        assert_eq!(ordered.len(), 2);

        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(Some(1)));
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(Some(2)));
        assert_eq!(Pin::new(&mut ordered).poll_next(&mut cx), Poll::Ready(None));
    }
}

Ursprungs-Seeder

csx-seed