Skip to content

Commit 94c9cb0

Browse files
cramertjboats
authored andcommitted
Add some async/await/StableFuture-related docs
1 parent 0c08606 commit 94c9cb0

File tree

3 files changed

+135
-0
lines changed

3 files changed

+135
-0
lines changed

futures-stable/src/executor.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ use futures_executor::{ThreadPool, LocalPool, LocalExecutor};
77
use StableFuture;
88
use UnsafePin;
99

10+
/// Executors which can spawn `PinBox`ed futures.
11+
///
12+
/// These executors can be used in combination with `StableFuture`s.
1013
pub trait StableExecutor: Executor {
14+
/// Spawn a `PinBox` future.
1115
fn spawn_pinned(&mut self, f: PinBox<Future<Item = (), Error = Never> + Send>) -> Result<(), SpawnError>;
1216
}
1317

@@ -23,6 +27,7 @@ impl StableExecutor for LocalExecutor {
2327
}
2428
}
2529

30+
/// Block on the result of a `StableFuture`.
2631
pub fn block_on_stable<F: StableFuture>(f: F) -> Result<F::Item, F::Error> {
2732
let mut pool = LocalPool::new();
2833
let mut exec = pool.executor();

futures-stable/src/lib.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,44 @@ if_nightly! {
3535
use unsafe_pin::UnsafePin;
3636
}
3737

38+
/// A trait for `Future`s which can be pinned to a particular location in memory.
39+
///
40+
/// These futures take `self` by `Pin<Self>`, rather than `&mut Self`.
41+
/// This allows types which are not [`Unpin`](::std::marker::Unpin) to guarantee
42+
/// that they won't be moved after being polled. Since they won't be moved, it's
43+
/// possible for them to safely contain references to themselves.
44+
///
45+
/// The most common examples of such self-referential `StableFuture`s are `#[async]`
46+
/// functions and `async_block!`s.
47+
///
48+
/// All types which implement `Future` also implement `StableFuture` automatically.
3849
pub trait StableFuture {
50+
/// A successful value
3951
type Item;
52+
53+
/// An error
4054
type Error;
4155

56+
/// Attempt to resolve the future to a final value, registering the current task
57+
/// for wakeup if the value is not yet available.
58+
///
59+
/// This method takes `self` by `Pin`, and so calling it requires putting `Self`
60+
/// in a [`PinBox`](::std::boxed::PinBox) using the `pin` method, or otherwise
61+
/// guaranteeing that the location of `self` will not change after a call to `poll`.
4262
fn poll(self: Pin<Self>, ctx: &mut task::Context) -> Poll<Self::Item, Self::Error>;
4363

64+
/// Pin the future to a particular location by placing it on the heap.
4465
#[cfg(feature = "std")]
4566
fn pin<'a>(self) -> PinBox<Future<Item = Self::Item, Error = Self::Error> + Send + 'a>
4667
where Self: Send + Sized + 'a
4768
{
4869
PinBox::new(unsafe { UnsafePin::new(self) })
4970
}
5071

72+
/// Pin the future to a particular location by placing it on the heap.
73+
///
74+
/// This method is the same as `pin`, but doesn't require that `Self` can be
75+
/// safely sent across threads. `pin` should be preferred where possible.
5176
#[cfg(feature = "std")]
5277
fn pin_local<'a>(self) -> PinBox<Future<Item = Self::Item, Error = Self::Error> + 'a>
5378
where Self: Sized + 'a
@@ -65,19 +90,43 @@ if_nightly! {
6590
}
6691
}
6792

93+
/// A trait for `Stream`s which can be pinned to a particular location in memory.
94+
///
95+
/// These streams take `self` by `Pin<Self>`, rather than `&mut Self`.
96+
/// This allows types which are not [`Unpin`](::std::marker::Unpin) to guarantee
97+
/// that they won't be moved after being polled. Since they won't be moved, it's
98+
/// possible for them to safely contain references to themselves.
99+
///
100+
/// The most common examples of such self-referential `StableStream`s are
101+
/// `#[async_stream(item = Foo)]` functions.
102+
///
103+
/// All types which implement `Stream` also implement `StableStream` automatically.
68104
pub trait StableStream {
105+
/// A successful value
69106
type Item;
107+
/// An error
70108
type Error;
71109

110+
/// Attempt to resolve the stream to the next value, registering the current task
111+
/// for wakeup if the value is not yet available.
112+
///
113+
/// This method takes `self` by `Pin`, and so calling it requires putting `Self`
114+
/// in a [`PinBox`](::std::boxed::PinBox) using the `pin` method, or otherwise
115+
/// guaranteeing that the location of `self` will not change after a call to `poll`.
72116
fn poll_next(self: Pin<Self>, ctx: &mut task::Context) -> Poll<Option<Self::Item>, Self::Error>;
73117

118+
/// Pin the stream to a particular location by placing it on the heap.
74119
#[cfg(feature = "std")]
75120
fn pin<'a>(self) -> PinBox<Stream<Item = Self::Item, Error = Self::Error> + Send + 'a>
76121
where Self: Send + Sized + 'a
77122
{
78123
PinBox::new(unsafe { UnsafePin::new(self) })
79124
}
80125

126+
/// Pin the stream to a particular location by placing it on the heap.
127+
///
128+
/// This method is the same as `pin`, but doesn't require that `Self` can be
129+
/// safely sent across threads. `pin` should be preferred where possible.
81130
#[cfg(feature = "std")]
82131
fn pin_local<'a>(self) -> PinBox<Stream<Item = Self::Item, Error = Self::Error> + 'a>
83132
where Self: Sized + 'a

futures/src/lib.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,87 @@ pub mod task {
401401

402402
#[cfg(feature = "nightly")]
403403
pub mod stable {
404+
//! `async/await` futures which can be pinned to a particular location.
405+
//!
406+
//! This module contains:
407+
//!
408+
//! - The [`StableFuture`](::StableFuture) and [`StableStream`](::StableStream)
409+
//! traits which allow for immovable, self-referential `Future`s and `Streams`.
410+
//!
411+
//! - The [`StableExecutor`](::StableExecutor) trait for `Executor`s which
412+
//! take [`PinBox`](::std::boxed:PinBox)ed `Future`s.
413+
//!
414+
//! - A [`block_on_stable`](::block_on_stable) function for blocking on
415+
//! `StableFuture`s.
416+
//!
417+
//! These immovable future types are most commonly used with the async/await
418+
//! macros, which are included in the prelude. These macros can be used to
419+
//! write asynchronous code in an ergonomic blocking style:
420+
//!
421+
//! ```rust
422+
//! /// A simple async function which returns immediately once polled:
423+
//! #[async]
424+
//! fn foo() -> Result<i32, i32> {
425+
//! Ok(1)
426+
//! }
427+
//!
428+
//! /// Async functions can `await!` the result of other async functions:
429+
//! #[async]
430+
//! fn bar() -> Result<i32, i32> {
431+
//! let foo_num = await!(foo())?;
432+
//! Ok(foo_num + 5)
433+
//! }
434+
//!
435+
//! /// Async functions can also choose to return a `Box`ed `Future` type.
436+
//! /// To opt into `Send`able futures, use `#[async(boxed, send)]`.
437+
//! #[async(boxed)]
438+
//! fn boxed(x: i32) -> Result<i32, i32> {
439+
//! Ok(
440+
//! await!(foo())? + await!(bar()) + x
441+
//! )
442+
//! }
443+
//!
444+
//! /// Async expressions can also be written in `async_block!`s:
445+
//! fn async_block() -> impl StableFuture<Item = i32, Error = i32> {
446+
//! println!("Runs before the future is returned");
447+
//! async_block! {
448+
//! println!("Runs the first time the future is polled");
449+
//! Ok(5)
450+
//! }
451+
//! }
452+
//!
453+
//! /// The futures that result from async functions can be pinned and used
454+
//! /// with other `Future` combinators:
455+
//! #[async]
456+
//! fn join_two_futures() -> Result<(i32, i32), i32> {
457+
//! let joined = foo().pin().join(bar().pin());
458+
//! await!(joined)
459+
//! }
460+
//!
461+
//! /// Streams can also be written in this style using the
462+
//! /// `#[async_stream(item = ItemType)]` macro. The `stream_yield!`
463+
//! /// macro is used to yield elements, and the `async_stream_block!`
464+
//! /// macro can be used to write async streams inside other functions:
465+
//! #[async_stream(boxed, send, item = u64)]
466+
//! fn stream_boxed() -> Result<(), i32> {
467+
//! let foo_result = await!(foo())?;
468+
//! stream_yield!(foo_result as u64);
469+
//! stream_yield!(22);
470+
//! Ok(())
471+
//! }
472+
//!
473+
//! /// Finally #[async] can be used on `for` loops to loop over the results
474+
//! /// of a stream:
475+
//! #[async]
476+
//! fn async_for() -> Result<(), i32> {
477+
//! #[async]
478+
//! for i in stream_boxed() {
479+
//! println!("yielded {}", i);
480+
//! }
481+
//! Ok(())
482+
//! }
483+
//! ```
484+
404485
pub use futures_stable::{StableFuture, StableStream};
405486

406487
#[cfg(feature = "std")]

0 commit comments

Comments
 (0)