#futures #channel #async

want

Detect when another Future wants a result

10 releases

0.3.1 Jun 14, 2023
0.3.0 Aug 20, 2019
0.2.0 Mar 19, 2019
0.1.0 Apr 6, 2018
0.0.2 Mar 16, 2018

#34 in Asynchronous

Download history 1132923/week @ 2023-11-03 1128917/week @ 2023-11-10 1078833/week @ 2023-11-17 1030572/week @ 2023-11-24 1130879/week @ 2023-12-01 1115144/week @ 2023-12-08 1020281/week @ 2023-12-15 604175/week @ 2023-12-22 817176/week @ 2023-12-29 1115348/week @ 2024-01-05 1163327/week @ 2024-01-12 1284788/week @ 2024-01-19 1286298/week @ 2024-01-26 1334476/week @ 2024-02-02 1335745/week @ 2024-02-09 1069543/week @ 2024-02-16

5,236,465 downloads per month
Used in 16,434 crates (5 directly)

MIT license

20KB
278 lines

Want

A Futures channel-like utility to signal when a value is wanted.

Futures are supposed to be lazy, and only starting work if Future::poll is called. The same is true of Streams, but when using a channel as a Stream, it can be hard to know if the receiver is ready for the next value.

Put another way, given a (tx, rx) from futures::sync::mpsc::channel(), how can the sender (tx) know when the receiver (rx) actually wants more work to be produced? Just because there is room in the channel buffer doesn't mean the work would be used by the receiver.

This is where something like want comes in. Added to a channel, you can make sure that the tx only creates the message and sends it when the rx has poll() for it, and the buffer was empty.

License

want is provided under the MIT license. See LICENSE.


lib.rs:

A Futures channel-like utility to signal when a value is wanted.

Futures are supposed to be lazy, and only starting work if Future::poll is called. The same is true of Streams, but when using a channel as a Stream, it can be hard to know if the receiver is ready for the next value.

Put another way, given a (tx, rx) from futures::sync::mpsc::channel(), how can the sender (tx) know when the receiver (rx) actually wants more work to be produced? Just because there is room in the channel buffer doesn't mean the work would be used by the receiver.

This is where something like want comes in. Added to a channel, you can make sure that the tx only creates the message and sends it when the rx has poll() for it, and the buffer was empty.

Example

extern crate want;


// Some message that is expensive to produce.
struct Expensive;

// Some futures-aware MPSC channel...
let (mut tx, mut rx) = mpsc_channel();

// And our `want` channel!
let (mut gv, mut tk) = want::new();


// Our receiving task...
spawn(async move {
    // Maybe something comes up that prevents us from ever
    // using the expensive message.
    //
    // Without `want`, the "send" task may have started to
    // produce the expensive message even though we wouldn't
    // be able to use it.
    if !we_still_want_message() {
        return;
    }

    // But we can use it! So tell the `want` channel.
    tk.want();

    match rx.recv().await {
        Some(_msg) => println!("got a message"),
        None => println!("DONE"),
    }
});

// Our sending task
spawn(async move {
    // It's expensive to create a new message, so we wait until the
    // receiving end truly *wants* the message.
    if let Err(_closed) = gv.want().await {
        // Looks like they will never want it...
        return;
    }

    // They want it, let's go!
    tx.send(Expensive);
});

Dependencies

~9KB