This commit is contained in:
Sean McArthur 2019-03-19 12:44:42 -07:00
parent abf58fd841
commit 0034cd2a66
4 changed files with 89 additions and 3 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "want"
version = "0.0.6" # remember to update html_root_url
version = "0.2.0" # remember to update html_root_url
description = "Detect when another Future wants a result."
keywords = ["futures", "channel"]
authors = ["Sean McArthur <sean@seanmonstar.com>"]

View File

@ -1,4 +1,4 @@
Copyright (c) 2018 Sean McArthur
Copyright (c) 2018-2019 Sean McArthur
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,3 +1,24 @@
# Want
- [Crates.io](https://crates.io/crates/want)
- [Docs](https://docs.rs/want)
A `Future`s 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 `Stream`s, 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](LICENSE).

View File

@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/want/0.0.6")]
#![doc(html_root_url = "https://docs.rs/want/0.2.0")]
#![deny(warnings)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
@ -18,6 +18,71 @@
//! 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 futures;
//! extern crate want;
//!
//! use futures::{Async, Stream};
//!
//! // Some message that is expensive to produce.
//! struct Expensive;
//!
//! let (mut tx, mut rx) = futures::sync::mpsc::channel(0);
//! let (mut gv, mut tk) = want::new();
//!
//! # fn spawn<T>(_t: T) {}
//! # fn can_we_print_msg() -> Result<(), ()> { Ok(()) }
//!
//! // Our receiving task...
//! spawn(futures::future::poll_fn(move || loop {
//!
//! match rx.poll() {
//! Ok(Async::Ready(Some(_msg))) => {
//! println!("got a message");
//! },
//! Ok(Async::Ready(None)) => {
//! println!("DONE");
//! return Ok::<_, ()>(Async::Ready(()));
//! },
//! Ok(Async::NotReady) => {
//! // 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.
//! can_we_print_msg()?;
//!
//! // But we can use it! So tell the `want` channel.
//! tk.want();
//! },
//! Err(()) => unreachable!("mpsc doesn't error"),
//! }
//! }));
//!
//! // Our sending task
//! spawn(futures::future::poll_fn(move || {
//! // It's expensive to create a new message, so we wait until the
//! // receiving end truly *wants* the message.
//! match gv.poll_want() {
//! Ok(Async::Ready(())) => {
//! // They want it, let's go!
//! tx.try_send(Expensive).unwrap();
//! Ok(Async::Ready(()))
//! },
//! Ok(Async::NotReady) => Ok(Async::NotReady),
//! Err(_) => {
//! // Looks like they will never want it...
//! Err(())
//! }
//! }
//! }));
//!
//! # fn main() {}
//! ```
extern crate futures;
#[macro_use]