ci: unfreeze wasm tests from rustc 1.88.0 (#7537)

This commit is contained in:
Lucas Black
2025-09-26 21:29:01 +08:00
committed by GitHub
parent bce76c515f
commit 8ccf2fb92e
74 changed files with 3496 additions and 3180 deletions
+8 -5
View File
@@ -988,10 +988,10 @@ jobs:
features: "macros sync time rt"
steps:
- uses: actions/checkout@v5
- name: Install Rust 1.88.0
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.88.0
toolchain: ${{ env.rust_stable }}
- name: Install wasm-pack
uses: taiki-e/install-action@wasm-pack
@@ -1011,10 +1011,10 @@ jobs:
- wasm32-wasip1-threads
steps:
- uses: actions/checkout@v4
- name: Install Rust 1.88.0
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.88.0
toolchain: ${{ env.rust_stable }}
targets: ${{ matrix.target }}
# Install dependencies
@@ -1025,11 +1025,14 @@ jobs:
- uses: Swatinem/rust-cache@v2
- name: WASI test tokio full
run: cargo test -p tokio --target ${{ matrix.target }} --features full
run: cargo test -p tokio --target ${{ matrix.target }} --features "sync,macros,io-util,rt,time"
env:
CARGO_TARGET_WASM32_WASIP1_RUNNER: "wasmtime run --"
CARGO_TARGET_WASM32_WASIP1_THREADS_RUNNER: "wasmtime run -W bulk-memory=y -W threads=y -S threads=y --"
RUSTFLAGS: --cfg tokio_unstable -Dwarnings -C target-feature=+atomics,+bulk-memory -C link-args=--max-memory=67108864
# in order to run doctests for unstable features, we must also pass
# the unstable cfg to RustDoc
RUSTDOCFLAGS: --cfg tokio_unstable
- name: WASI test tokio-util full
run: cargo test -p tokio-util --target ${{ matrix.target }} --features full
+5 -5
View File
@@ -26,12 +26,12 @@ unsafe impl<T> Sync for Empty<T> {}
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// let mut none = stream::empty::<i32>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut none = stream::empty::<i32>();
///
/// assert_eq!(None, none.next().await);
/// }
/// assert_eq!(None, none.next().await);
/// # }
/// ```
pub const fn empty<T>() -> Empty<T> {
Empty(PhantomData)
+6 -6
View File
@@ -34,14 +34,14 @@
//! ```rust
//! use tokio_stream::{self as stream, StreamExt};
//!
//! #[tokio::main]
//! async fn main() {
//! let mut stream = stream::iter(vec![0, 1, 2]);
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let mut stream = stream::iter(vec![0, 1, 2]);
//!
//! while let Some(value) = stream.next().await {
//! println!("Got {}", value);
//! }
//! while let Some(value) = stream.next().await {
//! println!("Got {}", value);
//! }
//! # }
//! ```
//!
//! # Returning a Stream from a function
+8 -8
View File
@@ -22,16 +22,16 @@ impl<I> Unpin for Once<I> {}
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// // one is the loneliest number
/// let mut one = stream::once(1);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// // one is the loneliest number
/// let mut one = stream::once(1);
///
/// assert_eq!(Some(1), one.next().await);
/// assert_eq!(Some(1), one.next().await);
///
/// // just one, that's all we get
/// assert_eq!(None, one.next().await);
/// }
/// // just one, that's all we get
/// assert_eq!(None, one.next().await);
/// # }
/// ```
pub fn once<T>(value: T) -> Once<T> {
Once {
+12 -12
View File
@@ -17,20 +17,20 @@ pin_project! {
/// ```
/// use tokio_stream::{StreamExt, StreamMap, StreamNotifyClose};
///
/// #[tokio::main]
/// async fn main() {
/// let mut map = StreamMap::new();
/// let stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// let stream2 = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// map.insert(0, stream);
/// map.insert(1, stream2);
/// while let Some((key, val)) = map.next().await {
/// match val {
/// Some(val) => println!("got {val:?} from stream {key:?}"),
/// None => println!("stream {key:?} closed"),
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut map = StreamMap::new();
/// let stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// let stream2 = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// map.insert(0, stream);
/// map.insert(1, stream2);
/// while let Some((key, val)) = map.next().await {
/// match val {
/// Some(val) => println!("got {val:?} from stream {key:?}"),
/// None => println!("stream {key:?} closed"),
/// }
/// }
/// # }
/// ```
#[must_use = "streams do nothing unless polled"]
pub struct StreamNotifyClose<S> {
+60 -56
View File
@@ -129,7 +129,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -171,8 +171,9 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
///
/// use tokio_stream::{self as stream, StreamExt};
///
/// let mut stream = stream::iter(vec![Ok(1), Ok(2), Err("nope")]);
@@ -203,7 +204,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -239,7 +240,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -283,7 +284,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -418,7 +419,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -454,7 +455,7 @@ pub trait StreamExt: Stream {
///
/// # Examples
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -514,7 +515,10 @@ pub trait StreamExt: Stream {
/// }
/// }
///
/// # /*
/// #[tokio::main]
/// # */
/// # #[tokio::main(flavor = "current_thread")]
/// async fn main() {
/// let mut stream = Alternate { state: 0 };
///
@@ -551,7 +555,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -580,7 +584,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -606,7 +610,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -637,7 +641,7 @@ pub trait StreamExt: Stream {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
/// let mut stream = stream::iter(vec![1,2,3,4,1]).skip_while(|x| *x < 3);
@@ -680,7 +684,7 @@ pub trait StreamExt: Stream {
/// Basic usage:
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -695,7 +699,7 @@ pub trait StreamExt: Stream {
/// Stopping at the first `false`:
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -739,7 +743,7 @@ pub trait StreamExt: Stream {
/// Basic usage:
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -754,7 +758,7 @@ pub trait StreamExt: Stream {
/// Stopping at the first `true`:
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
@@ -787,21 +791,21 @@ pub trait StreamExt: Stream {
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// let one = stream::iter(vec![1, 2, 3]);
/// let two = stream::iter(vec![4, 5, 6]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let one = stream::iter(vec![1, 2, 3]);
/// let two = stream::iter(vec![4, 5, 6]);
///
/// let mut stream = one.chain(two);
/// let mut stream = one.chain(two);
///
/// assert_eq!(stream.next().await, Some(1));
/// assert_eq!(stream.next().await, Some(2));
/// assert_eq!(stream.next().await, Some(3));
/// assert_eq!(stream.next().await, Some(4));
/// assert_eq!(stream.next().await, Some(5));
/// assert_eq!(stream.next().await, Some(6));
/// assert_eq!(stream.next().await, None);
/// }
/// assert_eq!(stream.next().await, Some(1));
/// assert_eq!(stream.next().await, Some(2));
/// assert_eq!(stream.next().await, Some(3));
/// assert_eq!(stream.next().await, Some(4));
/// assert_eq!(stream.next().await, Some(5));
/// assert_eq!(stream.next().await, Some(6));
/// assert_eq!(stream.next().await, None);
/// # }
/// ```
fn chain<U>(self, other: U) -> Chain<Self, U>
where
@@ -823,7 +827,7 @@ pub trait StreamExt: Stream {
/// # Examples
/// Basic usage:
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, *};
///
@@ -874,16 +878,16 @@ pub trait StreamExt: Stream {
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// let doubled: Vec<i32> =
/// stream::iter(vec![1, 2, 3])
/// .map(|x| x * 2)
/// .collect()
/// .await;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let doubled: Vec<i32> =
/// stream::iter(vec![1, 2, 3])
/// .map(|x| x * 2)
/// .collect()
/// .await;
///
/// assert_eq!(vec![2, 4, 6], doubled);
/// }
/// assert_eq!(vec![2, 4, 6], doubled);
/// # }
/// ```
///
/// Collecting a stream of `Result` values
@@ -891,26 +895,26 @@ pub trait StreamExt: Stream {
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// // A stream containing only `Ok` values will be collected
/// let values: Result<Vec<i32>, &str> =
/// stream::iter(vec![Ok(1), Ok(2), Ok(3)])
/// .collect()
/// .await;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// // A stream containing only `Ok` values will be collected
/// let values: Result<Vec<i32>, &str> =
/// stream::iter(vec![Ok(1), Ok(2), Ok(3)])
/// .collect()
/// .await;
///
/// assert_eq!(Ok(vec![1, 2, 3]), values);
/// assert_eq!(Ok(vec![1, 2, 3]), values);
///
/// // A stream containing `Err` values will return the first error.
/// let results = vec![Ok(1), Err("no"), Ok(2), Ok(3), Err("nein")];
/// // A stream containing `Err` values will return the first error.
/// let results = vec![Ok(1), Err("no"), Ok(2), Ok(3), Err("nein")];
///
/// let values: Result<Vec<i32>, &str> =
/// stream::iter(results)
/// .collect()
/// .await;
/// let values: Result<Vec<i32>, &str> =
/// stream::iter(results)
/// .collect()
/// .await;
///
/// assert_eq!(Err("no"), values);
/// }
/// assert_eq!(Err("no"), values);
/// # }
/// ```
fn collect<T>(self) -> Collect<Self, T>
where
@@ -945,7 +949,7 @@ pub trait StreamExt: Stream {
/// Suppose we have a stream `int_stream` that yields 3 numbers (1, 2, 3):
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
/// use std::time::Duration;
@@ -1031,7 +1035,7 @@ pub trait StreamExt: Stream {
/// Suppose we have a stream `int_stream` that yields 3 numbers (1, 2, 3):
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
/// use std::time::Duration;
+60 -60
View File
@@ -65,57 +65,57 @@ use std::task::{ready, Context, Poll};
/// use tokio::sync::mpsc;
/// use std::pin::Pin;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx1, mut rx1) = mpsc::channel::<usize>(10);
/// let (tx2, mut rx2) = mpsc::channel::<usize>(10);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx1, mut rx1) = mpsc::channel::<usize>(10);
/// let (tx2, mut rx2) = mpsc::channel::<usize>(10);
///
/// // Convert the channels to a `Stream`.
/// let rx1 = Box::pin(async_stream::stream! {
/// while let Some(item) = rx1.recv().await {
/// yield item;
/// }
/// }) as Pin<Box<dyn Stream<Item = usize> + Send>>;
///
/// let rx2 = Box::pin(async_stream::stream! {
/// while let Some(item) = rx2.recv().await {
/// yield item;
/// }
/// }) as Pin<Box<dyn Stream<Item = usize> + Send>>;
///
/// tokio::spawn(async move {
/// tx1.send(1).await.unwrap();
///
/// // This value will never be received. The send may or may not return
/// // `Err` depending on if the remote end closed first or not.
/// let _ = tx1.send(2).await;
/// });
///
/// tokio::spawn(async move {
/// tx2.send(3).await.unwrap();
/// let _ = tx2.send(4).await;
/// });
///
/// let mut map = StreamMap::new();
///
/// // Insert both streams
/// map.insert("one", rx1);
/// map.insert("two", rx2);
///
/// // Read twice
/// for _ in 0..2 {
/// let (key, val) = map.next().await.unwrap();
///
/// if key == "one" {
/// assert_eq!(val, 1);
/// } else {
/// assert_eq!(val, 3);
/// }
///
/// // Remove the stream to prevent reading the next value
/// map.remove(key);
/// // Convert the channels to a `Stream`.
/// let rx1 = Box::pin(async_stream::stream! {
/// while let Some(item) = rx1.recv().await {
/// yield item;
/// }
/// }) as Pin<Box<dyn Stream<Item = usize> + Send>>;
///
/// let rx2 = Box::pin(async_stream::stream! {
/// while let Some(item) = rx2.recv().await {
/// yield item;
/// }
/// }) as Pin<Box<dyn Stream<Item = usize> + Send>>;
///
/// tokio::spawn(async move {
/// tx1.send(1).await.unwrap();
///
/// // This value will never be received. The send may or may not return
/// // `Err` depending on if the remote end closed first or not.
/// let _ = tx1.send(2).await;
/// });
///
/// tokio::spawn(async move {
/// tx2.send(3).await.unwrap();
/// let _ = tx2.send(4).await;
/// });
///
/// let mut map = StreamMap::new();
///
/// // Insert both streams
/// map.insert("one", rx1);
/// map.insert("two", rx2);
///
/// // Read twice
/// for _ in 0..2 {
/// let (key, val) = map.next().await.unwrap();
///
/// if key == "one" {
/// assert_eq!(val, 1);
/// } else {
/// assert_eq!(val, 3);
/// }
///
/// // Remove the stream to prevent reading the next value
/// map.remove(key);
/// }
/// # }
/// ```
///
/// This example models a read-only client to a chat system with channels. The
@@ -185,20 +185,20 @@ use std::task::{ready, Context, Poll};
/// ```
/// use tokio_stream::{StreamExt, StreamMap, StreamNotifyClose};
///
/// #[tokio::main]
/// async fn main() {
/// let mut map = StreamMap::new();
/// let stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// let stream2 = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// map.insert(0, stream);
/// map.insert(1, stream2);
/// while let Some((key, val)) = map.next().await {
/// match val {
/// Some(val) => println!("got {val:?} from stream {key:?}"),
/// None => println!("stream {key:?} closed"),
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut map = StreamMap::new();
/// let stream = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// let stream2 = StreamNotifyClose::new(tokio_stream::iter(vec![0, 1]));
/// map.insert(0, stream);
/// map.insert(1, stream2);
/// while let Some((key, val)) = map.next().await {
/// match val {
/// Some(val) => println!("got {val:?} from stream {key:?}"),
/// None => println!("stream {key:?} closed"),
/// }
/// }
/// # }
/// ```
#[derive(Debug)]
@@ -11,6 +11,8 @@ use tokio::net::{TcpListener, TcpStream};
/// Accept connections from both IPv4 and IPv6 listeners in the same loop:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::net::{Ipv4Addr, Ipv6Addr};
///
/// use tokio::net::TcpListener;
@@ -31,6 +33,7 @@ use tokio::net::{TcpListener, TcpStream};
/// }
/// # Ok(())
/// # }
/// # }
/// ```
///
/// [`TcpListener`]: struct@tokio::net::TcpListener
+3 -3
View File
@@ -17,7 +17,7 @@ use tokio::sync::watch::error::RecvError;
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{StreamExt, wrappers::WatchStream};
/// use tokio::sync::watch;
@@ -33,7 +33,7 @@ use tokio::sync::watch::error::RecvError;
/// ```
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{StreamExt, wrappers::WatchStream};
/// use tokio::sync::watch;
@@ -51,7 +51,7 @@ use tokio::sync::watch::error::RecvError;
/// Example with [`WatchStream<T>::from_changes`]:
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use futures::future::FutureExt;
/// use tokio::sync::watch;
+7 -7
View File
@@ -81,7 +81,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x0BHello world";
//! let mut reader = LengthDelimitedCodec::builder()
@@ -117,7 +117,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x0BHello world";
//! let mut reader = LengthDelimitedCodec::builder()
@@ -154,7 +154,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x0DHello world";
//! let mut reader = LengthDelimitedCodec::builder()
@@ -190,7 +190,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x00\x0B\xCA\xFEHello world";
//! let mut reader = LengthDelimitedCodec::builder()
@@ -237,7 +237,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\xCA\x00\x0B\xFEHello world";
//! let mut reader = LengthDelimitedCodec::builder()
@@ -286,7 +286,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\xCA\x00\x0F\xFEHello world";
//! let mut reader = LengthDelimitedCodec::builder()
@@ -329,7 +329,7 @@
//! ```
//! # use tokio_stream::StreamExt;
//! # use tokio_util::codec::LengthDelimitedCodec;
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! # let io: &[u8] = b"\x00\x00\x0B\xFFHello world";
//! let mut reader = LengthDelimitedCodec::builder()
+31 -31
View File
@@ -19,25 +19,25 @@
//! use tokio_util::codec::LinesCodec;
//! use tokio_util::codec::FramedWrite;
//!
//! #[tokio::main]
//! async fn main() {
//! let buffer = Vec::new();
//! let messages = vec!["Hello", "World"];
//! let encoder = LinesCodec::new();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let buffer = Vec::new();
//! let messages = vec!["Hello", "World"];
//! let encoder = LinesCodec::new();
//!
//! // FramedWrite is a sink which means you can send values into it
//! // asynchronously.
//! let mut writer = FramedWrite::new(buffer, encoder);
//! // FramedWrite is a sink which means you can send values into it
//! // asynchronously.
//! let mut writer = FramedWrite::new(buffer, encoder);
//!
//! // To be able to send values into a FramedWrite, you need to bring the
//! // `SinkExt` trait into scope.
//! writer.send(messages[0]).await.unwrap();
//! writer.send(messages[1]).await.unwrap();
//! // To be able to send values into a FramedWrite, you need to bring the
//! // `SinkExt` trait into scope.
//! writer.send(messages[0]).await.unwrap();
//! writer.send(messages[1]).await.unwrap();
//!
//! let buffer = writer.get_ref();
//! let buffer = writer.get_ref();
//!
//! assert_eq!(buffer.as_slice(), "Hello\nWorld\n".as_bytes());
//! }
//! assert_eq!(buffer.as_slice(), "Hello\nWorld\n".as_bytes());
//! # }
//!```
//!
//! # Example decoding using `LinesCodec`
@@ -51,25 +51,25 @@
//! use tokio_util::codec::LinesCodec;
//! use tokio_util::codec::FramedRead;
//!
//! #[tokio::main]
//! async fn main() {
//! let message = "Hello\nWorld".as_bytes();
//! let decoder = LinesCodec::new();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let message = "Hello\nWorld".as_bytes();
//! let decoder = LinesCodec::new();
//!
//! // FramedRead can be used to read a stream of values that are framed according to
//! // a codec. FramedRead will read from its input (here `buffer`) until a whole frame
//! // can be parsed.
//! let mut reader = FramedRead::new(message, decoder);
//! // FramedRead can be used to read a stream of values that are framed according to
//! // a codec. FramedRead will read from its input (here `buffer`) until a whole frame
//! // can be parsed.
//! let mut reader = FramedRead::new(message, decoder);
//!
//! // To read values from a FramedRead, you need to bring the
//! // `StreamExt` trait into scope.
//! let frame1 = reader.next().await.unwrap().unwrap();
//! let frame2 = reader.next().await.unwrap().unwrap();
//! // To read values from a FramedRead, you need to bring the
//! // `StreamExt` trait into scope.
//! let frame1 = reader.next().await.unwrap().unwrap();
//! let frame2 = reader.next().await.unwrap().unwrap();
//!
//! assert!(reader.next().await.is_none());
//! assert_eq!(frame1, "Hello");
//! assert_eq!(frame2, "World");
//! }
//! assert!(reader.next().await.is_none());
//! assert_eq!(frame1, "Hello");
//! assert_eq!(frame2, "World");
//! # }
//! ```
//!
//! # The Decoder trait
+6
View File
@@ -34,6 +34,8 @@
//! stream via [`compat()`].
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::net::{TcpListener, TcpStream};
//! use tokio::io::AsyncWriteExt;
//! use tokio_util::compat::TokioAsyncReadCompatExt;
@@ -58,6 +60,7 @@
//!
//! Ok(())
//! }
//! # }
//! ```
//!
//! ## Example 2: Futures -> Tokio (`AsyncRead`)
@@ -66,6 +69,8 @@
//! adapt it to be used with [`tokio::io::AsyncReadExt::read_to_end`]
//!
//! ```
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use futures::io::Cursor;
//! use tokio_util::compat::FuturesAsyncReadCompatExt;
//! use tokio::io::AsyncReadExt;
@@ -82,6 +87,7 @@
//! // Run the future inside a Tokio runtime
//! tokio::runtime::Runtime::new().unwrap().block_on(future);
//! }
//! # }
//! ```
//!
//! ## Common Use Cases
+9
View File
@@ -37,6 +37,8 @@ pin_project! {
/// them. It then uses the context of the runtime with the timer enabled to
/// execute a [`sleep`] future on the runtime with timing disabled.
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::time::{sleep, Duration};
/// use tokio_util::context::RuntimeExt;
///
@@ -56,6 +58,7 @@ pin_project! {
///
/// // Execute the future on rt2.
/// rt2.block_on(fut);
/// # }
/// ```
///
/// [`Handle`]: struct@tokio::runtime::Handle
@@ -88,6 +91,8 @@ impl<F> TokioContext<F> {
/// [`RuntimeExt::wrap`]: fn@RuntimeExt::wrap
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::time::{sleep, Duration};
/// use tokio_util::context::TokioContext;
///
@@ -109,6 +114,7 @@ impl<F> TokioContext<F> {
///
/// // Execute the future on rt2.
/// rt2.block_on(fut);
/// # }
/// ```
pub fn new(future: F, handle: Handle) -> TokioContext<F> {
TokioContext {
@@ -153,6 +159,8 @@ pub trait RuntimeExt {
/// execute a [`sleep`] future on the runtime with timing disabled.
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::time::{sleep, Duration};
/// use tokio_util::context::RuntimeExt;
///
@@ -172,6 +180,7 @@ pub trait RuntimeExt {
///
/// // Execute the future on rt2.
/// rt2.block_on(fut);
/// # }
/// ```
///
/// [`TokioContext`]: struct@crate::context::TokioContext
+11 -11
View File
@@ -46,18 +46,18 @@ use tokio::io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, ReadBuf, Result}
/// # async fn some_async_function() -> u32 { 10 }
/// # async fn other_async_function() -> u32 { 20 }
///
/// #[tokio::main]
/// async fn main() {
/// let result = if some_condition() {
/// Either::Left(some_async_function())
/// } else {
/// Either::Right(other_async_function())
/// };
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let result = if some_condition() {
/// Either::Left(some_async_function())
/// } else {
/// Either::Right(other_async_function())
/// };
///
/// let value = result.await;
/// println!("Result is {}", value);
/// # assert_eq!(value, 10);
/// }
/// let value = result.await;
/// println!("Result is {}", value);
/// # assert_eq!(value, 10);
/// # }
/// ```
#[allow(missing_docs)] // Doc-comments for variants in this particular case don't make much sense.
#[derive(Debug, Clone)]
+1 -1
View File
@@ -10,7 +10,7 @@ use tokio::io::{AsyncRead, AsyncReadExt};
/// # Example
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> std::io::Result<()> {
/// use tokio_util::io::read_exact_arc;
///
+1 -1
View File
@@ -16,7 +16,7 @@ use tokio::io::AsyncRead;
/// use tokio_stream as stream;
/// use tokio::io::Result;
/// use tokio_util::io::{StreamReader, read_buf};
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> std::io::Result<()> {
///
/// // Create a reader from an iterator. This particular reader will always be
+1 -1
View File
@@ -16,7 +16,7 @@ pin_project! {
/// # Example
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> std::io::Result<()> {
/// use tokio_stream::StreamExt;
/// use tokio_util::io::ReaderStream;
+21 -18
View File
@@ -57,15 +57,15 @@ use tokio::io::{
/// let hash = blake3::hash(&data);
///
/// Ok(hash)
///}
///
/// #[tokio::main]
/// async fn main() -> Result<(), std::io::Error> {
/// // Example: In-memory data.
/// let data = b"Hello, world!"; // A byte slice.
/// let reader = Cursor::new(data); // Create an in-memory AsyncRead.
/// hash_contents(reader).await
/// }
///
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), std::io::Error> {
/// // Example: In-memory data.
/// let data = b"Hello, world!"; // A byte slice.
/// let reader = Cursor::new(data); // Create an in-memory AsyncRead.
/// hash_contents(reader).await
/// # }
/// ```
///
/// When the data doesn't fit into memory, the hashing library will usually
@@ -88,7 +88,7 @@ use tokio::io::{
/// /// and hashes the data incrementally.
/// async fn hash_stream(mut reader: impl AsyncRead + Unpin, mut hasher: Hasher) -> Result<(), std::io::Error> {
/// // Create a buffer to read data into, sized for performance.
/// let mut data = vec![0; 64 * 1024];
/// let mut data = vec![0; 16 * 1024];
/// loop {
/// // Read data from the reader into the buffer.
/// let len = reader.read(&mut data).await?;
@@ -102,16 +102,16 @@ use tokio::io::{
/// let hash = hasher.finalize();
///
/// Ok(hash)
///}
///
/// #[tokio::main]
/// async fn main() -> Result<(), std::io::Error> {
/// // Example: In-memory data.
/// let data = b"Hello, world!"; // A byte slice.
/// let reader = Cursor::new(data); // Create an in-memory AsyncRead.
/// let hasher = Hasher;
/// hash_stream(reader, hasher).await
/// }
///
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), std::io::Error> {
/// // Example: In-memory data.
/// let data = b"Hello, world!"; // A byte slice.
/// let reader = Cursor::new(data); // Create an in-memory AsyncRead.
/// let hasher = Hasher;
/// hash_stream(reader, hasher).await
/// # }
/// ```
///
///
@@ -218,6 +218,8 @@ use tokio::io::{
/// thread pool, preventing it from interfering with the async tasks.
///
/// ```rust
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::task::spawn_blocking;
/// use tokio_util::io::SyncIoBridge;
/// use tokio::io::AsyncRead;
@@ -255,6 +257,7 @@ use tokio::io::{
///
/// Ok(())
/// }
/// # }
/// ```
///
#[derive(Debug)]
+42 -42
View File
@@ -36,28 +36,28 @@ use tokio::task::{AbortHandle, Id, JoinError, JoinSet, LocalSet};
/// ```
/// use tokio_util::task::JoinMap;
///
/// #[tokio::main]
/// async fn main() {
/// let mut map = JoinMap::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut map = JoinMap::new();
///
/// for i in 0..10 {
/// // Spawn a task on the `JoinMap` with `i` as its key.
/// map.spawn(i, async move { /* ... */ });
/// }
///
/// let mut seen = [false; 10];
///
/// // When a task completes, `join_next` returns the task's key along
/// // with its output.
/// while let Some((key, res)) = map.join_next().await {
/// seen[key] = true;
/// assert!(res.is_ok(), "task {} completed successfully!", key);
/// }
///
/// for i in 0..10 {
/// assert!(seen[i]);
/// }
/// for i in 0..10 {
/// // Spawn a task on the `JoinMap` with `i` as its key.
/// map.spawn(i, async move { /* ... */ });
/// }
///
/// let mut seen = [false; 10];
///
/// // When a task completes, `join_next` returns the task's key along
/// // with its output.
/// while let Some((key, res)) = map.join_next().await {
/// seen[key] = true;
/// assert!(res.is_ok(), "task {} completed successfully!", key);
/// }
///
/// for i in 0..10 {
/// assert!(seen[i]);
/// }
/// # }
/// ```
///
/// Cancel tasks based on their keys:
@@ -65,30 +65,30 @@ use tokio::task::{AbortHandle, Id, JoinError, JoinSet, LocalSet};
/// ```
/// use tokio_util::task::JoinMap;
///
/// #[tokio::main]
/// async fn main() {
/// let mut map = JoinMap::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut map = JoinMap::new();
///
/// map.spawn("hello world", std::future::ready(1));
/// map.spawn("goodbye world", std::future::pending());
/// map.spawn("hello world", std::future::ready(1));
/// map.spawn("goodbye world", std::future::pending());
///
/// // Look up the "goodbye world" task in the map and abort it.
/// let aborted = map.abort("goodbye world");
/// // Look up the "goodbye world" task in the map and abort it.
/// let aborted = map.abort("goodbye world");
///
/// // `JoinMap::abort` returns `true` if a task existed for the
/// // provided key.
/// assert!(aborted);
/// // `JoinMap::abort` returns `true` if a task existed for the
/// // provided key.
/// assert!(aborted);
///
/// while let Some((key, res)) = map.join_next().await {
/// if key == "goodbye world" {
/// // The aborted task should complete with a cancelled `JoinError`.
/// assert!(res.unwrap_err().is_cancelled());
/// } else {
/// // Other tasks should complete normally.
/// assert_eq!(res.unwrap(), 1);
/// }
/// while let Some((key, res)) = map.join_next().await {
/// if key == "goodbye world" {
/// // The aborted task should complete with a cancelled `JoinError`.
/// assert!(res.unwrap_err().is_cancelled());
/// } else {
/// // Other tasks should complete normally.
/// assert_eq!(res.unwrap(), 1);
/// }
/// }
/// # }
/// ```
///
/// [`JoinSet`]: tokio::task::JoinSet
@@ -186,7 +186,7 @@ impl<K, V, S> JoinMap<K, V, S> {
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_util::task::JoinMap;
/// use std::collections::hash_map::RandomState;
@@ -521,7 +521,7 @@ where
/// ```
/// use tokio_util::task::JoinMap;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut map = JoinMap::new();
///
@@ -686,7 +686,7 @@ where
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_util::task::JoinMap;
///
@@ -715,7 +715,7 @@ where
/// # Examples
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_util::task::JoinMap;
///
+9
View File
@@ -22,6 +22,8 @@ use tokio::task::{spawn_local, JoinHandle, LocalSet};
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::rc::Rc;
/// use tokio::task;
/// use tokio_util::task::LocalPoolHandle;
@@ -45,6 +47,7 @@ use tokio::task::{spawn_local, JoinHandle, LocalSet};
/// }).await.unwrap();
/// println!("output: {}", output);
/// }
/// # }
/// ```
///
#[derive(Clone)]
@@ -94,6 +97,8 @@ impl LocalPoolHandle {
///
/// # Examples
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::rc::Rc;
/// use tokio_util::task::LocalPoolHandle;
///
@@ -116,6 +121,7 @@ impl LocalPoolHandle {
///
/// assert_eq!(output, "test");
/// }
/// # }
/// ```
pub fn spawn_pinned<F, Fut>(&self, create_task: F) -> JoinHandle<Fut::Output>
where
@@ -144,6 +150,8 @@ impl LocalPoolHandle {
/// This method can be used to spawn a task on all worker threads of the pool:
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio_util::task::LocalPoolHandle;
///
/// #[tokio::main]
@@ -167,6 +175,7 @@ impl LocalPoolHandle {
/// handle.await.unwrap();
/// }
/// }
/// # }
/// ```
///
#[track_caller]
+15 -15
View File
@@ -66,23 +66,23 @@ use tokio::{
/// ```
/// use tokio_util::task::TaskTracker;
///
/// #[tokio::main]
/// async fn main() {
/// let tracker = TaskTracker::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let tracker = TaskTracker::new();
///
/// for i in 0..10 {
/// tracker.spawn(async move {
/// println!("Task {} is running!", i);
/// });
/// }
/// // Once we spawned everything, we close the tracker.
/// tracker.close();
///
/// // Wait for everything to finish.
/// tracker.wait().await;
///
/// println!("This is printed after all of the tasks.");
/// for i in 0..10 {
/// tracker.spawn(async move {
/// println!("Task {} is running!", i);
/// });
/// }
/// // Once we spawned everything, we close the tracker.
/// tracker.close();
///
/// // Wait for everything to finish.
/// tracker.wait().await;
///
/// println!("This is printed after all of the tasks.");
/// # }
/// ```
///
/// ## Wait for tasks to exit
+13 -13
View File
@@ -461,7 +461,7 @@ impl<T> DelayQueue<T> {
/// # use tokio_util::time::DelayQueue;
/// # use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::with_capacity(10);
///
@@ -517,7 +517,7 @@ impl<T> DelayQueue<T> {
/// use tokio::time::{Duration, Instant};
/// use tokio_util::time::DelayQueue;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
/// let key = delay_queue.insert_at(
@@ -637,7 +637,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
/// let key = delay_queue.insert("foo", Duration::from_secs(5));
@@ -692,7 +692,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
///
@@ -743,7 +743,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
/// let key = delay_queue.insert("foo", Duration::from_secs(5));
@@ -841,7 +841,7 @@ impl<T> DelayQueue<T> {
/// use tokio::time::{Duration, Instant};
/// use tokio_util::time::DelayQueue;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
/// let key = delay_queue.insert("foo", Duration::from_secs(5));
@@ -898,7 +898,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::with_capacity(10);
///
@@ -931,7 +931,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
///
@@ -983,7 +983,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
/// let key = delay_queue.insert("foo", Duration::from_secs(5));
@@ -1014,7 +1014,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
///
@@ -1056,7 +1056,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue: DelayQueue<i32> = DelayQueue::with_capacity(10);
/// assert_eq!(delay_queue.len(), 0);
@@ -1091,7 +1091,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
///
@@ -1121,7 +1121,7 @@ impl<T> DelayQueue<T> {
/// use tokio_util::time::DelayQueue;
/// use std::time::Duration;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut delay_queue = DelayQueue::new();
/// assert!(delay_queue.is_empty());
+1 -1
View File
@@ -18,7 +18,7 @@ use std::task::{ready, Context, Poll};
/// use tokio_util::io::{StreamReader, poll_read_buf};
/// use std::future::poll_fn;
/// use std::pin::Pin;
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> std::io::Result<()> {
///
/// // Create a reader from an iterator. This particular reader will always be
+9
View File
@@ -36,6 +36,8 @@
//! can do the same with [`tokio::fs::File`][`File`]:
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::io::{self, AsyncReadExt};
//! use tokio::fs::File;
//!
@@ -50,6 +52,7 @@
//! println!("The bytes: {:?}", &buffer[..n]);
//! Ok(())
//! }
//! # }
//! ```
//!
//! [`File`]: crate::fs::File
@@ -73,6 +76,8 @@
//! extra methods to any async reader:
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::io::{self, BufReader, AsyncBufReadExt};
//! use tokio::fs::File;
//!
@@ -88,6 +93,7 @@
//! println!("{}", buffer);
//! Ok(())
//! }
//! # }
//! ```
//!
//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
@@ -95,6 +101,8 @@
//! [`BufWriter`] to ensure that any buffered data is written.
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::io::{self, BufWriter, AsyncWriteExt};
//! use tokio::fs::File;
//!
@@ -114,6 +122,7 @@
//!
//! Ok(())
//! }
//! # }
//! ```
//!
//! [stdbuf]: std::io#bufreader-and-bufwriter
+59 -59
View File
@@ -62,36 +62,36 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() {
/// let mut cursor = Cursor::new(b"lorem-ipsum");
/// let mut buf = vec![];
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut cursor = Cursor::new(b"lorem-ipsum");
/// let mut buf = vec![];
///
/// // cursor is at 'l'
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// // cursor is at 'l'
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .await
/// .expect("reading from cursor won't fail");
///
/// assert_eq!(num_bytes, 6);
/// assert_eq!(buf, b"lorem-");
/// buf.clear();
/// assert_eq!(num_bytes, 6);
/// assert_eq!(buf, b"lorem-");
/// buf.clear();
///
/// // cursor is at 'i'
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// // cursor is at 'i'
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .await
/// .expect("reading from cursor won't fail");
///
/// assert_eq!(num_bytes, 5);
/// assert_eq!(buf, b"ipsum");
/// buf.clear();
/// assert_eq!(num_bytes, 5);
/// assert_eq!(buf, b"ipsum");
/// buf.clear();
///
/// // cursor is at EOF
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 0);
/// assert_eq!(buf, b"");
/// }
/// // cursor is at EOF
/// let num_bytes = cursor.read_until(b'-', &mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// assert_eq!(num_bytes, 0);
/// assert_eq!(buf, b"");
/// # }
/// ```
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
where
@@ -164,37 +164,37 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() {
/// let mut cursor = Cursor::new(b"foo\nbar");
/// let mut buf = String::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut cursor = Cursor::new(b"foo\nbar");
/// let mut buf = String::new();
///
/// // cursor is at 'f'
/// let num_bytes = cursor.read_line(&mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// // cursor is at 'f'
/// let num_bytes = cursor.read_line(&mut buf)
/// .await
/// .expect("reading from cursor won't fail");
///
/// assert_eq!(num_bytes, 4);
/// assert_eq!(buf, "foo\n");
/// buf.clear();
/// assert_eq!(num_bytes, 4);
/// assert_eq!(buf, "foo\n");
/// buf.clear();
///
/// // cursor is at 'b'
/// let num_bytes = cursor.read_line(&mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// // cursor is at 'b'
/// let num_bytes = cursor.read_line(&mut buf)
/// .await
/// .expect("reading from cursor won't fail");
///
/// assert_eq!(num_bytes, 3);
/// assert_eq!(buf, "bar");
/// buf.clear();
/// assert_eq!(num_bytes, 3);
/// assert_eq!(buf, "bar");
/// buf.clear();
///
/// // cursor is at EOF
/// let num_bytes = cursor.read_line(&mut buf)
/// .await
/// .expect("reading from cursor won't fail");
/// // cursor is at EOF
/// let num_bytes = cursor.read_line(&mut buf)
/// .await
/// .expect("reading from cursor won't fail");
///
/// assert_eq!(num_bytes, 0);
/// assert_eq!(buf, "");
/// }
/// assert_eq!(num_bytes, 0);
/// assert_eq!(buf, "");
/// # }
/// ```
fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
where
@@ -331,17 +331,17 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() {
/// let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let cursor = Cursor::new(b"lorem\nipsum\r\ndolor");
///
/// let mut lines = cursor.lines();
/// let mut lines = cursor.lines();
///
/// assert_eq!(lines.next_line().await.unwrap(), Some(String::from("lorem")));
/// assert_eq!(lines.next_line().await.unwrap(), Some(String::from("ipsum")));
/// assert_eq!(lines.next_line().await.unwrap(), Some(String::from("dolor")));
/// assert_eq!(lines.next_line().await.unwrap(), None);
/// }
/// assert_eq!(lines.next_line().await.unwrap(), Some(String::from("lorem")));
/// assert_eq!(lines.next_line().await.unwrap(), Some(String::from("ipsum")));
/// assert_eq!(lines.next_line().await.unwrap(), Some(String::from("dolor")));
/// assert_eq!(lines.next_line().await.unwrap(), None);
/// # }
/// ```
///
/// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
+181 -157
View File
@@ -41,6 +41,8 @@ cfg_io_util! {
/// [`AsyncRead`].
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
@@ -54,6 +56,7 @@ cfg_io_util! {
///
/// Ok(())
/// }
/// # }
/// ```
///
/// See [module][crate::io] documentation for more details.
@@ -72,6 +75,8 @@ cfg_io_util! {
/// [`File`][crate::fs::File]s implement `AsyncRead`:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
@@ -88,6 +93,7 @@ cfg_io_util! {
/// handle.read_to_string(&mut buffer).await?;
/// Ok(())
/// }
/// # }
/// ```
fn chain<R>(self, next: R) -> Chain<Self, R>
where
@@ -150,6 +156,8 @@ cfg_io_util! {
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
@@ -164,6 +172,7 @@ cfg_io_util! {
/// println!("The bytes: {:?}", &buffer[..n]);
/// Ok(())
/// }
/// # }
/// ```
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>
where
@@ -219,6 +228,8 @@ cfg_io_util! {
/// [`BufMut`]: bytes::BufMut
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
@@ -242,6 +253,7 @@ cfg_io_util! {
/// println!("The bytes: {:?}", &buffer[..]);
/// Ok(())
/// }
/// # }
/// ```
fn read_buf<'a, B>(&'a mut self, buf: &'a mut B) -> ReadBuf<'a, Self, B>
where
@@ -289,6 +301,8 @@ cfg_io_util! {
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
@@ -302,6 +316,7 @@ cfg_io_util! {
/// f.read_exact(&mut buffer).await?;
/// Ok(())
/// }
/// # }
/// ```
///
/// [`ErrorKind::UnexpectedEof`]: std::io::ErrorKind::UnexpectedEof
@@ -345,15 +360,15 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![2, 5]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![2, 5]);
///
/// assert_eq!(2, reader.read_u8().await?);
/// assert_eq!(5, reader.read_u8().await?);
/// assert_eq!(2, reader.read_u8().await?);
/// assert_eq!(5, reader.read_u8().await?);
///
/// Ok(())
/// }
/// Ok(())
/// # }
/// ```
fn read_u8(&mut self) -> ReadU8;
@@ -389,15 +404,15 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x02, 0xfb]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x02, 0xfb]);
///
/// assert_eq!(2, reader.read_i8().await?);
/// assert_eq!(-5, reader.read_i8().await?);
/// assert_eq!(2, reader.read_i8().await?);
/// assert_eq!(-5, reader.read_i8().await?);
///
/// Ok(())
/// }
/// Ok(())
/// # }
/// ```
fn read_i8(&mut self) -> ReadI8;
@@ -434,14 +449,14 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![2, 5, 3, 0]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![2, 5, 3, 0]);
///
/// assert_eq!(517, reader.read_u16().await?);
/// assert_eq!(768, reader.read_u16().await?);
/// Ok(())
/// }
/// assert_eq!(517, reader.read_u16().await?);
/// assert_eq!(768, reader.read_u16().await?);
/// Ok(())
/// # }
/// ```
fn read_u16(&mut self) -> ReadU16;
@@ -478,14 +493,14 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]);
///
/// assert_eq!(193, reader.read_i16().await?);
/// assert_eq!(-132, reader.read_i16().await?);
/// Ok(())
/// }
/// assert_eq!(193, reader.read_i16().await?);
/// assert_eq!(-132, reader.read_i16().await?);
/// Ok(())
/// # }
/// ```
fn read_i16(&mut self) -> ReadI16;
@@ -522,13 +537,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]);
///
/// assert_eq!(267, reader.read_u32().await?);
/// Ok(())
/// }
/// assert_eq!(267, reader.read_u32().await?);
/// Ok(())
/// # }
/// ```
fn read_u32(&mut self) -> ReadU32;
@@ -566,13 +581,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]);
///
/// assert_eq!(-34253, reader.read_i32().await?);
/// Ok(())
/// }
/// assert_eq!(-34253, reader.read_i32().await?);
/// Ok(())
/// # }
/// ```
fn read_i32(&mut self) -> ReadI32;
@@ -609,15 +624,15 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
///
/// assert_eq!(918733457491587, reader.read_u64().await?);
/// Ok(())
/// }
/// assert_eq!(918733457491587, reader.read_u64().await?);
/// Ok(())
/// # }
/// ```
fn read_u64(&mut self) -> ReadU64;
@@ -654,13 +669,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]);
///
/// assert_eq!(i64::MIN, reader.read_i64().await?);
/// Ok(())
/// }
/// assert_eq!(i64::MIN, reader.read_i64().await?);
/// Ok(())
/// # }
/// ```
fn read_i64(&mut self) -> ReadI64;
@@ -697,16 +712,16 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
///
/// assert_eq!(16947640962301618749969007319746179, reader.read_u128().await?);
/// Ok(())
/// }
/// assert_eq!(16947640962301618749969007319746179, reader.read_u128().await?);
/// Ok(())
/// # }
/// ```
fn read_u128(&mut self) -> ReadU128;
@@ -743,16 +758,16 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0
/// ]);
///
/// assert_eq!(i128::MIN, reader.read_i128().await?);
/// Ok(())
/// }
/// assert_eq!(i128::MIN, reader.read_i128().await?);
/// Ok(())
/// # }
/// ```
fn read_i128(&mut self) -> ReadI128;
@@ -789,13 +804,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0x7f, 0xff, 0xff]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0x7f, 0xff, 0xff]);
///
/// assert_eq!(f32::MIN, reader.read_f32().await?);
/// Ok(())
/// }
/// assert_eq!(f32::MIN, reader.read_f32().await?);
/// Ok(())
/// # }
/// ```
fn read_f32(&mut self) -> ReadF32;
@@ -832,15 +847,15 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
/// ]);
///
/// assert_eq!(f64::MIN, reader.read_f64().await?);
/// Ok(())
/// }
/// assert_eq!(f64::MIN, reader.read_f64().await?);
/// Ok(())
/// # }
/// ```
fn read_f64(&mut self) -> ReadF64;
@@ -877,14 +892,14 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![2, 5, 3, 0]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![2, 5, 3, 0]);
///
/// assert_eq!(1282, reader.read_u16_le().await?);
/// assert_eq!(3, reader.read_u16_le().await?);
/// Ok(())
/// }
/// assert_eq!(1282, reader.read_u16_le().await?);
/// assert_eq!(3, reader.read_u16_le().await?);
/// Ok(())
/// # }
/// ```
fn read_u16_le(&mut self) -> ReadU16Le;
@@ -921,14 +936,14 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0xc1, 0xff, 0x7c]);
///
/// assert_eq!(-16128, reader.read_i16_le().await?);
/// assert_eq!(31999, reader.read_i16_le().await?);
/// Ok(())
/// }
/// assert_eq!(-16128, reader.read_i16_le().await?);
/// assert_eq!(31999, reader.read_i16_le().await?);
/// Ok(())
/// # }
/// ```
fn read_i16_le(&mut self) -> ReadI16Le;
@@ -965,13 +980,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x00, 0x00, 0x01, 0x0b]);
///
/// assert_eq!(184614912, reader.read_u32_le().await?);
/// Ok(())
/// }
/// assert_eq!(184614912, reader.read_u32_le().await?);
/// Ok(())
/// # }
/// ```
fn read_u32_le(&mut self) -> ReadU32Le;
@@ -1009,13 +1024,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7a, 0x33]);
///
/// assert_eq!(863698943, reader.read_i32_le().await?);
/// Ok(())
/// }
/// assert_eq!(863698943, reader.read_i32_le().await?);
/// Ok(())
/// # }
/// ```
fn read_i32_le(&mut self) -> ReadI32Le;
@@ -1052,15 +1067,15 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
///
/// assert_eq!(9477368352180732672, reader.read_u64_le().await?);
/// Ok(())
/// }
/// assert_eq!(9477368352180732672, reader.read_u64_le().await?);
/// Ok(())
/// # }
/// ```
fn read_u64_le(&mut self) -> ReadU64Le;
@@ -1097,13 +1112,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0]);
///
/// assert_eq!(128, reader.read_i64_le().await?);
/// Ok(())
/// }
/// assert_eq!(128, reader.read_i64_le().await?);
/// Ok(())
/// # }
/// ```
fn read_i64_le(&mut self) -> ReadI64Le;
@@ -1140,16 +1155,16 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
///
/// assert_eq!(174826588484952389081207917399662330624, reader.read_u128_le().await?);
/// Ok(())
/// }
/// assert_eq!(174826588484952389081207917399662330624, reader.read_u128_le().await?);
/// Ok(())
/// # }
/// ```
fn read_u128_le(&mut self) -> ReadU128Le;
@@ -1186,16 +1201,16 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0
/// ]);
///
/// assert_eq!(128, reader.read_i128_le().await?);
/// Ok(())
/// }
/// assert_eq!(128, reader.read_i128_le().await?);
/// Ok(())
/// # }
/// ```
fn read_i128_le(&mut self) -> ReadI128Le;
@@ -1232,13 +1247,13 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7f, 0xff]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![0xff, 0xff, 0x7f, 0xff]);
///
/// assert_eq!(f32::MIN, reader.read_f32_le().await?);
/// Ok(())
/// }
/// assert_eq!(f32::MIN, reader.read_f32_le().await?);
/// Ok(())
/// # }
/// ```
fn read_f32_le(&mut self) -> ReadF32Le;
@@ -1275,15 +1290,15 @@ cfg_io_util! {
///
/// use std::io::Cursor;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff
/// ]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut reader = Cursor::new(vec![
/// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff
/// ]);
///
/// assert_eq!(f64::MIN, reader.read_f64_le().await?);
/// Ok(())
/// }
/// assert_eq!(f64::MIN, reader.read_f64_le().await?);
/// Ok(())
/// # }
/// ```
fn read_f64_le(&mut self) -> ReadF64Le;
}
@@ -1315,6 +1330,8 @@ cfg_io_util! {
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncReadExt};
/// use tokio::fs::File;
///
@@ -1327,6 +1344,7 @@ cfg_io_util! {
/// f.read_to_end(&mut buffer).await?;
/// Ok(())
/// }
/// # }
/// ```
///
/// (See also the [`tokio::fs::read`] convenience function for reading from a
@@ -1363,6 +1381,8 @@ cfg_io_util! {
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncReadExt};
/// use tokio::fs::File;
///
@@ -1374,6 +1394,7 @@ cfg_io_util! {
/// f.read_to_string(&mut buffer).await?;
/// Ok(())
/// }
/// # }
/// ```
///
/// (See also the [`crate::fs::read_to_string`] convenience function for
@@ -1403,6 +1424,8 @@ cfg_io_util! {
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncReadExt};
/// use tokio::fs::File;
///
@@ -1417,6 +1440,7 @@ cfg_io_util! {
/// handle.read(&mut buffer).await?;
/// Ok(())
/// }
/// # }
/// ```
fn take(self, limit: u64) -> Take<Self>
where
+14 -11
View File
@@ -11,20 +11,20 @@ cfg_io_util! {
/// use std::io::{self, Cursor, SeekFrom};
/// use tokio::io::{AsyncSeekExt, AsyncReadExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut cursor = Cursor::new(b"abcdefg");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut cursor = Cursor::new(b"abcdefg");
///
/// // the `seek` method is defined by this trait
/// cursor.seek(SeekFrom::Start(3)).await?;
/// // the `seek` method is defined by this trait
/// cursor.seek(SeekFrom::Start(3)).await?;
///
/// let mut buf = [0; 1];
/// let n = cursor.read(&mut buf).await?;
/// assert_eq!(n, 1);
/// assert_eq!(buf, [b'd']);
/// let mut buf = [0; 1];
/// let n = cursor.read(&mut buf).await?;
/// assert_eq!(n, 1);
/// assert_eq!(buf, [b'd']);
///
/// Ok(())
/// }
/// Ok(())
/// # }
/// ```
///
/// See [module][crate::io] documentation for more details.
@@ -46,6 +46,8 @@ cfg_io_util! {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::fs::File;
/// use tokio::io::{AsyncSeekExt, AsyncReadExt};
///
@@ -59,6 +61,7 @@ cfg_io_util! {
/// file.read_exact(&mut contents).await?;
/// # Ok(())
/// # }
/// # }
/// ```
fn seek(&mut self, pos: SeekFrom) -> Seek<'_, Self>
where
+208 -184
View File
@@ -44,6 +44,8 @@ cfg_io_util! {
/// [`AsyncWrite`].
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -61,6 +63,7 @@ cfg_io_util! {
///
/// Ok(())
/// }
/// # }
/// ```
///
/// See [module][crate::io] documentation for more details.
@@ -108,6 +111,8 @@ cfg_io_util! {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -120,6 +125,7 @@ cfg_io_util! {
/// file.flush().await?;
/// Ok(())
/// }
/// # }
/// ```
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where
@@ -148,6 +154,8 @@ cfg_io_util! {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
/// use std::io::IoSlice;
@@ -167,6 +175,7 @@ cfg_io_util! {
///
/// Ok(())
/// }
/// # }
/// ```
///
/// [`write`]: AsyncWriteExt::write
@@ -228,6 +237,8 @@ cfg_io_util! {
/// [`Cursor`]: std::io::Cursor
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -250,6 +261,7 @@ cfg_io_util! {
///
/// Ok(())
/// }
/// # }
/// ```
fn write_buf<'a, B>(&'a mut self, src: &'a mut B) -> WriteBuf<'a, Self, B>
where
@@ -299,6 +311,8 @@ cfg_io_util! {
/// [advanced]: bytes::Buf::advance
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -313,6 +327,7 @@ cfg_io_util! {
/// file.flush().await?;
/// Ok(())
/// }
/// # }
/// ```
///
/// [`write`]: AsyncWriteExt::write
@@ -352,6 +367,8 @@ cfg_io_util! {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -363,6 +380,7 @@ cfg_io_util! {
/// file.flush().await?;
/// Ok(())
/// }
/// # }
/// ```
///
/// [`write`]: AsyncWriteExt::write
@@ -398,16 +416,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u8(2).await?;
/// writer.write_u8(5).await?;
/// writer.write_u8(2).await?;
/// writer.write_u8(5).await?;
///
/// assert_eq!(writer, b"\x02\x05");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x02\x05");
/// Ok(())
/// # }
/// ```
fn write_u8(&mut self, n: u8) -> WriteU8;
@@ -435,16 +453,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i8(-2).await?;
/// writer.write_i8(126).await?;
/// writer.write_i8(-2).await?;
/// writer.write_i8(126).await?;
///
/// assert_eq!(writer, b"\xFE\x7E");
/// Ok(())
/// }
/// assert_eq!(writer, b"\xFE\x7E");
/// Ok(())
/// # }
/// ```
fn write_i8(&mut self, n: i8) -> WriteI8;
@@ -473,16 +491,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u16(517).await?;
/// writer.write_u16(768).await?;
/// writer.write_u16(517).await?;
/// writer.write_u16(768).await?;
///
/// assert_eq!(writer, b"\x02\x05\x03\x00");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x02\x05\x03\x00");
/// Ok(())
/// # }
/// ```
fn write_u16(&mut self, n: u16) -> WriteU16;
@@ -511,16 +529,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i16(193).await?;
/// writer.write_i16(-132).await?;
/// writer.write_i16(193).await?;
/// writer.write_i16(-132).await?;
///
/// assert_eq!(writer, b"\x00\xc1\xff\x7c");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x00\xc1\xff\x7c");
/// Ok(())
/// # }
/// ```
fn write_i16(&mut self, n: i16) -> WriteI16;
@@ -549,16 +567,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u32(267).await?;
/// writer.write_u32(1205419366).await?;
/// writer.write_u32(267).await?;
/// writer.write_u32(1205419366).await?;
///
/// assert_eq!(writer, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
/// Ok(())
/// # }
/// ```
fn write_u32(&mut self, n: u32) -> WriteU32;
@@ -587,16 +605,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i32(267).await?;
/// writer.write_i32(1205419366).await?;
/// writer.write_i32(267).await?;
/// writer.write_i32(1205419366).await?;
///
/// assert_eq!(writer, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x00\x00\x01\x0b\x47\xd9\x3d\x66");
/// Ok(())
/// # }
/// ```
fn write_i32(&mut self, n: i32) -> WriteI32;
@@ -625,16 +643,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u64(918733457491587).await?;
/// writer.write_u64(143).await?;
/// writer.write_u64(918733457491587).await?;
/// writer.write_u64(143).await?;
///
/// assert_eq!(writer, b"\x00\x03\x43\x95\x4d\x60\x86\x83\x00\x00\x00\x00\x00\x00\x00\x8f");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x00\x03\x43\x95\x4d\x60\x86\x83\x00\x00\x00\x00\x00\x00\x00\x8f");
/// Ok(())
/// # }
/// ```
fn write_u64(&mut self, n: u64) -> WriteU64;
@@ -663,16 +681,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i64(i64::MIN).await?;
/// writer.write_i64(i64::MAX).await?;
/// writer.write_i64(i64::MIN).await?;
/// writer.write_i64(i64::MAX).await?;
///
/// assert_eq!(writer, b"\x80\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x80\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff");
/// Ok(())
/// # }
/// ```
fn write_i64(&mut self, n: i64) -> WriteI64;
@@ -701,18 +719,18 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u128(16947640962301618749969007319746179).await?;
/// writer.write_u128(16947640962301618749969007319746179).await?;
///
/// assert_eq!(writer, vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83,
/// 0x00, 0x03, 0x43, 0x95, 0x4d, 0x60, 0x86, 0x83
/// ]);
/// Ok(())
/// # }
/// ```
fn write_u128(&mut self, n: u128) -> WriteU128;
@@ -741,18 +759,18 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i128(i128::MIN).await?;
/// writer.write_i128(i128::MIN).await?;
///
/// assert_eq!(writer, vec![
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0
/// ]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![
/// 0x80, 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0
/// ]);
/// Ok(())
/// # }
/// ```
fn write_i128(&mut self, n: i128) -> WriteI128;
@@ -781,15 +799,15 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_f32(f32::MIN).await?;
/// writer.write_f32(f32::MIN).await?;
///
/// assert_eq!(writer, vec![0xff, 0x7f, 0xff, 0xff]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![0xff, 0x7f, 0xff, 0xff]);
/// Ok(())
/// # }
/// ```
fn write_f32(&mut self, n: f32) -> WriteF32;
@@ -818,17 +836,17 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_f64(f64::MIN).await?;
/// writer.write_f64(f64::MIN).await?;
///
/// assert_eq!(writer, vec![
/// 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
/// ]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![
/// 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
/// ]);
/// Ok(())
/// # }
/// ```
fn write_f64(&mut self, n: f64) -> WriteF64;
@@ -857,16 +875,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u16_le(517).await?;
/// writer.write_u16_le(768).await?;
/// writer.write_u16_le(517).await?;
/// writer.write_u16_le(768).await?;
///
/// assert_eq!(writer, b"\x05\x02\x00\x03");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x05\x02\x00\x03");
/// Ok(())
/// # }
/// ```
fn write_u16_le(&mut self, n: u16) -> WriteU16Le;
@@ -895,16 +913,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i16_le(193).await?;
/// writer.write_i16_le(-132).await?;
/// writer.write_i16_le(193).await?;
/// writer.write_i16_le(-132).await?;
///
/// assert_eq!(writer, b"\xc1\x00\x7c\xff");
/// Ok(())
/// }
/// assert_eq!(writer, b"\xc1\x00\x7c\xff");
/// Ok(())
/// # }
/// ```
fn write_i16_le(&mut self, n: i16) -> WriteI16Le;
@@ -933,16 +951,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u32_le(267).await?;
/// writer.write_u32_le(1205419366).await?;
/// writer.write_u32_le(267).await?;
/// writer.write_u32_le(1205419366).await?;
///
/// assert_eq!(writer, b"\x0b\x01\x00\x00\x66\x3d\xd9\x47");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x0b\x01\x00\x00\x66\x3d\xd9\x47");
/// Ok(())
/// # }
/// ```
fn write_u32_le(&mut self, n: u32) -> WriteU32Le;
@@ -971,16 +989,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i32_le(267).await?;
/// writer.write_i32_le(1205419366).await?;
/// writer.write_i32_le(267).await?;
/// writer.write_i32_le(1205419366).await?;
///
/// assert_eq!(writer, b"\x0b\x01\x00\x00\x66\x3d\xd9\x47");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x0b\x01\x00\x00\x66\x3d\xd9\x47");
/// Ok(())
/// # }
/// ```
fn write_i32_le(&mut self, n: i32) -> WriteI32Le;
@@ -1009,16 +1027,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u64_le(918733457491587).await?;
/// writer.write_u64_le(143).await?;
/// writer.write_u64_le(918733457491587).await?;
/// writer.write_u64_le(143).await?;
///
/// assert_eq!(writer, b"\x83\x86\x60\x4d\x95\x43\x03\x00\x8f\x00\x00\x00\x00\x00\x00\x00");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x83\x86\x60\x4d\x95\x43\x03\x00\x8f\x00\x00\x00\x00\x00\x00\x00");
/// Ok(())
/// # }
/// ```
fn write_u64_le(&mut self, n: u64) -> WriteU64Le;
@@ -1047,16 +1065,16 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i64_le(i64::MIN).await?;
/// writer.write_i64_le(i64::MAX).await?;
/// writer.write_i64_le(i64::MIN).await?;
/// writer.write_i64_le(i64::MAX).await?;
///
/// assert_eq!(writer, b"\x00\x00\x00\x00\x00\x00\x00\x80\xff\xff\xff\xff\xff\xff\xff\x7f");
/// Ok(())
/// }
/// assert_eq!(writer, b"\x00\x00\x00\x00\x00\x00\x00\x80\xff\xff\xff\xff\xff\xff\xff\x7f");
/// Ok(())
/// # }
/// ```
fn write_i64_le(&mut self, n: i64) -> WriteI64Le;
@@ -1085,18 +1103,18 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_u128_le(16947640962301618749969007319746179).await?;
/// writer.write_u128_le(16947640962301618749969007319746179).await?;
///
/// assert_eq!(writer, vec![
/// 0x83, 0x86, 0x60, 0x4d, 0x95, 0x43, 0x03, 0x00,
/// 0x83, 0x86, 0x60, 0x4d, 0x95, 0x43, 0x03, 0x00,
/// ]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![
/// 0x83, 0x86, 0x60, 0x4d, 0x95, 0x43, 0x03, 0x00,
/// 0x83, 0x86, 0x60, 0x4d, 0x95, 0x43, 0x03, 0x00,
/// ]);
/// Ok(())
/// # }
/// ```
fn write_u128_le(&mut self, n: u128) -> WriteU128Le;
@@ -1125,18 +1143,18 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_i128_le(i128::MIN).await?;
/// writer.write_i128_le(i128::MIN).await?;
///
/// assert_eq!(writer, vec![
/// 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0, 0x80
/// ]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![
/// 0, 0, 0, 0, 0, 0, 0,
/// 0, 0, 0, 0, 0, 0, 0, 0, 0x80
/// ]);
/// Ok(())
/// # }
/// ```
fn write_i128_le(&mut self, n: i128) -> WriteI128Le;
@@ -1165,15 +1183,15 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_f32_le(f32::MIN).await?;
/// writer.write_f32_le(f32::MIN).await?;
///
/// assert_eq!(writer, vec![0xff, 0xff, 0x7f, 0xff]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![0xff, 0xff, 0x7f, 0xff]);
/// Ok(())
/// # }
/// ```
fn write_f32_le(&mut self, n: f32) -> WriteF32Le;
@@ -1202,17 +1220,17 @@ cfg_io_util! {
/// ```rust
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let mut writer = Vec::new();
///
/// writer.write_f64_le(f64::MIN).await?;
/// writer.write_f64_le(f64::MIN).await?;
///
/// assert_eq!(writer, vec![
/// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff
/// ]);
/// Ok(())
/// }
/// assert_eq!(writer, vec![
/// 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff
/// ]);
/// Ok(())
/// # }
/// ```
fn write_f64_le(&mut self, n: f64) -> WriteF64Le;
}
@@ -1244,6 +1262,8 @@ cfg_io_util! {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, BufWriter, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -1256,6 +1276,7 @@ cfg_io_util! {
/// buffer.flush().await?;
/// Ok(())
/// }
/// # }
/// ```
fn flush(&mut self) -> Flush<'_, Self>
where
@@ -1283,6 +1304,8 @@ cfg_io_util! {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::io::{self, BufWriter, AsyncWriteExt};
/// use tokio::fs::File;
///
@@ -1295,6 +1318,7 @@ cfg_io_util! {
/// buffer.shutdown().await?;
/// Ok(())
/// }
/// # }
/// ```
fn shutdown(&mut self) -> Shutdown<'_, Self>
where
+9 -9
View File
@@ -39,12 +39,12 @@ cfg_io_util! {
/// ```
/// use tokio::io::{self, AsyncReadExt};
///
/// #[tokio::main]
/// async fn main() {
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).await.unwrap();
/// assert!(buffer.is_empty());
/// }
/// # }
/// ```
///
/// A convoluted way of getting the length of a buffer:
@@ -52,12 +52,12 @@ cfg_io_util! {
/// ```
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() {
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::empty().write(&buffer).await.unwrap();
/// assert_eq!(num_bytes, 5);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::empty().write(&buffer).await.unwrap();
/// assert_eq!(num_bytes, 5);
/// # }
/// ```
pub fn empty() -> Empty {
Empty { _p: () }
+6 -6
View File
@@ -37,12 +37,12 @@ cfg_io_util! {
/// ```
/// use tokio::io::{self, AsyncReadExt};
///
/// #[tokio::main]
/// async fn main() {
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).await.unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).await.unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// # }
/// ```
pub fn repeat(byte: u8) -> Repeat {
Repeat { byte }
+7 -7
View File
@@ -37,13 +37,13 @@ cfg_io_util! {
/// ```
/// use tokio::io::{self, AsyncWriteExt};
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).await?;
/// assert_eq!(num_bytes, 5);
/// Ok(())
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).await?;
/// assert_eq!(num_bytes, 5);
/// Ok(())
/// # }
/// ```
pub fn sink() -> Sink {
Sink { _p: () }
+6
View File
@@ -194,6 +194,8 @@
//! [`thread_keep_alive`]: crate::runtime::Builder::thread_keep_alive()
//!
//! ```
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! #[tokio::main]
//! async fn main() {
//! // This is running on a core thread.
@@ -208,6 +210,7 @@
//! // panic.
//! blocking_task.await.unwrap();
//! }
//! # }
//! ```
//!
//! If your code is CPU-bound and you wish to limit the number of threads used
@@ -266,6 +269,8 @@
//! A simple TCP echo server:
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::net::TcpListener;
//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
//!
@@ -300,6 +305,7 @@
//! });
//! }
//! }
//! # }
//! ```
//!
//! # Feature flags
+6
View File
@@ -12,6 +12,8 @@ use std::time::{Duration, Instant};
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::{Arc, Barrier};
/// use std::thread;
///
@@ -31,6 +33,7 @@ use std::time::{Duration, Instant};
/// for handle in handles {
/// handle.join().unwrap();
/// }
/// # }
/// ```
pub(crate) struct Barrier {
lock: Mutex<BarrierState>,
@@ -103,6 +106,8 @@ impl Barrier {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::{Arc, Barrier};
/// use std::thread;
///
@@ -122,6 +127,7 @@ impl Barrier {
/// for handle in handles {
/// handle.join().unwrap();
/// }
/// # }
/// ```
pub(crate) fn wait(&self) -> BarrierWaitResult {
let mut lock = self.lock.lock();
+19 -16
View File
@@ -64,19 +64,21 @@ macro_rules! doc {
/// // more here
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let (first, second) = tokio::join!(
/// do_stuff_async(),
/// more_async_work());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (first, second) = tokio::join!(
/// do_stuff_async(),
/// more_async_work());
///
/// // do something with the values
/// }
/// // do something with the values
/// # }
/// ```
///
/// Using the `biased;` mode to control polling order.
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// async fn do_stuff_async() {
/// // async work
/// }
@@ -85,16 +87,17 @@ macro_rules! doc {
/// // more here
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let (first, second) = tokio::join!(
/// biased;
/// do_stuff_async(),
/// more_async_work()
/// );
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (first, second) = tokio::join!(
/// biased;
/// do_stuff_async(),
/// more_async_work()
/// );
///
/// // do something with the values
/// }
/// // do something with the values
/// # }
/// # }
/// ```
#[macro_export]
+31 -31
View File
@@ -31,13 +31,13 @@
/// // async logic here
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let future = my_async_fn();
/// pin!(future);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let future = my_async_fn();
/// pin!(future);
///
/// (&mut future).await;
/// }
/// (&mut future).await;
/// # }
/// ```
///
/// Pinning is useful when using `select!` and stream operators that require `T:
@@ -77,25 +77,25 @@
/// // async logic here
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let mut stream = stream::iter(vec![1, 2, 3, 4]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut stream = stream::iter(vec![1, 2, 3, 4]);
///
/// let future = my_async_fn();
/// pin!(future);
/// let future = my_async_fn();
/// pin!(future);
///
/// loop {
/// select! {
/// _ = &mut future => {
/// // Stop looping `future` will be polled after completion
/// break;
/// }
/// Some(val) = stream.next() => {
/// println!("got value = {}", val);
/// }
/// loop {
/// select! {
/// _ = &mut future => {
/// // Stop looping `future` will be polled after completion
/// break;
/// }
/// Some(val) = stream.next() => {
/// println!("got value = {}", val);
/// }
/// }
/// }
/// # }
/// ```
///
/// Because assigning to a variable followed by pinning is common, there is also
@@ -108,18 +108,18 @@
/// // async logic here
/// }
///
/// #[tokio::main]
/// async fn main() {
/// pin! {
/// let future1 = my_async_fn();
/// let future2 = my_async_fn();
/// }
///
/// select! {
/// _ = &mut future1 => {}
/// _ = &mut future2 => {}
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// pin! {
/// let future1 = my_async_fn();
/// let future2 = my_async_fn();
/// }
///
/// select! {
/// _ = &mut future1 => {}
/// _ = &mut future2 => {}
/// }
/// # }
/// ```
#[macro_export]
macro_rules! pin {
+173 -174
View File
@@ -158,17 +158,17 @@ macro_rules! doc {
/// // more here
/// }
///
/// #[tokio::main]
/// async fn main() {
/// tokio::select! {
/// _ = do_stuff_async() => {
/// println!("do_stuff_async() completed first")
/// }
/// _ = more_async_work() => {
/// println!("more_async_work() completed first")
/// }
/// };
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// tokio::select! {
/// _ = do_stuff_async() => {
/// println!("do_stuff_async() completed first")
/// }
/// _ = more_async_work() => {
/// println!("more_async_work() completed first")
/// }
/// };
/// # }
/// ```
///
/// Basic stream selecting.
@@ -176,18 +176,18 @@ macro_rules! doc {
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// let mut stream1 = stream::iter(vec![1, 2, 3]);
/// let mut stream2 = stream::iter(vec![4, 5, 6]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut stream1 = stream::iter(vec![1, 2, 3]);
/// let mut stream2 = stream::iter(vec![4, 5, 6]);
///
/// let next = tokio::select! {
/// v = stream1.next() => v.unwrap(),
/// v = stream2.next() => v.unwrap(),
/// };
/// let next = tokio::select! {
/// v = stream1.next() => v.unwrap(),
/// v = stream2.next() => v.unwrap(),
/// };
///
/// assert!(next == 1 || next == 4);
/// }
/// assert!(next == 1 || next == 4);
/// # }
/// ```
///
/// Collect the contents of two streams. In this example, we rely on pattern
@@ -197,24 +197,24 @@ macro_rules! doc {
/// ```
/// use tokio_stream::{self as stream, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
/// let mut stream1 = stream::iter(vec![1, 2, 3]);
/// let mut stream2 = stream::iter(vec![4, 5, 6]);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut stream1 = stream::iter(vec![1, 2, 3]);
/// let mut stream2 = stream::iter(vec![4, 5, 6]);
///
/// let mut values = vec![];
/// let mut values = vec![];
///
/// loop {
/// tokio::select! {
/// Some(v) = stream1.next() => values.push(v),
/// Some(v) = stream2.next() => values.push(v),
/// else => break,
/// }
/// loop {
/// tokio::select! {
/// Some(v) = stream1.next() => values.push(v),
/// Some(v) = stream2.next() => values.push(v),
/// else => break,
/// }
///
/// values.sort();
/// assert_eq!(&[1, 2, 3, 4, 5, 6], &values[..]);
/// }
///
/// values.sort();
/// assert_eq!(&[1, 2, 3, 4, 5, 6], &values[..]);
/// # }
/// ```
///
/// Using the same future in multiple `select!` expressions can be done by passing
@@ -230,28 +230,28 @@ macro_rules! doc {
/// use tokio_stream::{self as stream, StreamExt};
/// use tokio::time::{self, Duration};
///
/// #[tokio::main]
/// async fn main() {
/// let mut stream = stream::iter(vec![1, 2, 3]);
/// let sleep = time::sleep(Duration::from_secs(1));
/// tokio::pin!(sleep);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut stream = stream::iter(vec![1, 2, 3]);
/// let sleep = time::sleep(Duration::from_secs(1));
/// tokio::pin!(sleep);
///
/// loop {
/// tokio::select! {
/// maybe_v = stream.next() => {
/// if let Some(v) = maybe_v {
/// println!("got = {}", v);
/// } else {
/// break;
/// }
/// }
/// _ = &mut sleep => {
/// println!("timeout");
/// loop {
/// tokio::select! {
/// maybe_v = stream.next() => {
/// if let Some(v) = maybe_v {
/// println!("got = {}", v);
/// } else {
/// break;
/// }
/// }
/// _ = &mut sleep => {
/// println!("timeout");
/// break;
/// }
/// }
/// }
/// # }
/// ```
///
/// Joining two values using `select!`.
@@ -259,73 +259,73 @@ macro_rules! doc {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx1, mut rx1) = oneshot::channel();
/// let (tx2, mut rx2) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx1, mut rx1) = oneshot::channel();
/// let (tx2, mut rx2) = oneshot::channel();
///
/// tokio::spawn(async move {
/// tx1.send("first").unwrap();
/// });
/// tokio::spawn(async move {
/// tx1.send("first").unwrap();
/// });
///
/// tokio::spawn(async move {
/// tx2.send("second").unwrap();
/// });
/// tokio::spawn(async move {
/// tx2.send("second").unwrap();
/// });
///
/// let mut a = None;
/// let mut b = None;
/// let mut a = None;
/// let mut b = None;
///
/// while a.is_none() || b.is_none() {
/// tokio::select! {
/// v1 = (&mut rx1), if a.is_none() => a = Some(v1.unwrap()),
/// v2 = (&mut rx2), if b.is_none() => b = Some(v2.unwrap()),
/// }
/// while a.is_none() || b.is_none() {
/// tokio::select! {
/// v1 = (&mut rx1), if a.is_none() => a = Some(v1.unwrap()),
/// v2 = (&mut rx2), if b.is_none() => b = Some(v2.unwrap()),
/// }
///
/// let res = (a.unwrap(), b.unwrap());
///
/// assert_eq!(res.0, "first");
/// assert_eq!(res.1, "second");
/// }
///
/// let res = (a.unwrap(), b.unwrap());
///
/// assert_eq!(res.0, "first");
/// assert_eq!(res.1, "second");
/// # }
/// ```
///
/// Using the `biased;` mode to control polling order.
///
/// ```
/// #[tokio::main]
/// async fn main() {
/// let mut count = 0u8;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut count = 0u8;
///
/// loop {
/// tokio::select! {
/// // If you run this example without `biased;`, the polling order is
/// // pseudo-random, and the assertions on the value of count will
/// // (probably) fail.
/// biased;
/// loop {
/// tokio::select! {
/// // If you run this example without `biased;`, the polling order is
/// // pseudo-random, and the assertions on the value of count will
/// // (probably) fail.
/// biased;
///
/// _ = async {}, if count < 1 => {
/// count += 1;
/// assert_eq!(count, 1);
/// }
/// _ = async {}, if count < 2 => {
/// count += 1;
/// assert_eq!(count, 2);
/// }
/// _ = async {}, if count < 3 => {
/// count += 1;
/// assert_eq!(count, 3);
/// }
/// _ = async {}, if count < 4 => {
/// count += 1;
/// assert_eq!(count, 4);
/// }
/// _ = async {}, if count < 1 => {
/// count += 1;
/// assert_eq!(count, 1);
/// }
/// _ = async {}, if count < 2 => {
/// count += 1;
/// assert_eq!(count, 2);
/// }
/// _ = async {}, if count < 3 => {
/// count += 1;
/// assert_eq!(count, 3);
/// }
/// _ = async {}, if count < 4 => {
/// count += 1;
/// assert_eq!(count, 4);
/// }
///
/// else => {
/// break;
/// }
/// };
/// }
/// else => {
/// break;
/// }
/// };
/// }
/// # }
/// ```
///
/// ## Avoid racy `if` preconditions
@@ -344,24 +344,24 @@ macro_rules! doc {
/// // do work
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let sleep = time::sleep(Duration::from_millis(50));
/// tokio::pin!(sleep);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let sleep = time::sleep(Duration::from_millis(50));
/// tokio::pin!(sleep);
///
/// while !sleep.is_elapsed() {
/// tokio::select! {
/// _ = &mut sleep, if !sleep.is_elapsed() => {
/// println!("operation timed out");
/// }
/// _ = some_async_work() => {
/// println!("operation completed");
/// }
/// while !sleep.is_elapsed() {
/// tokio::select! {
/// _ = &mut sleep, if !sleep.is_elapsed() => {
/// println!("operation timed out");
/// }
/// _ = some_async_work() => {
/// println!("operation completed");
/// }
/// }
///
/// panic!("This example shows how not to do it!");
/// }
///
/// panic!("This example shows how not to do it!");
/// # }
/// ```
///
/// In the above example, `sleep.is_elapsed()` may return `true` even if
@@ -380,23 +380,23 @@ macro_rules! doc {
/// // do work
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let sleep = time::sleep(Duration::from_millis(50));
/// tokio::pin!(sleep);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let sleep = time::sleep(Duration::from_millis(50));
/// tokio::pin!(sleep);
///
/// loop {
/// tokio::select! {
/// _ = &mut sleep => {
/// println!("operation timed out");
/// break;
/// }
/// _ = some_async_work() => {
/// println!("operation completed");
/// }
/// loop {
/// tokio::select! {
/// _ = &mut sleep => {
/// println!("operation timed out");
/// break;
/// }
/// _ = some_async_work() => {
/// println!("operation completed");
/// }
/// }
/// }
/// # }
/// ```
/// # Alternatives from the Ecosystem
///
@@ -437,22 +437,21 @@ macro_rules! doc {
/// // do work that is not cancel safe
/// }
///
/// #[tokio::main]
/// async fn main() {
/// // open our IO types
/// let mut file = File;
/// let mut channel = Channel;
/// let mut socket = Socket;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// // open our IO types
/// let mut file = File;
/// let mut channel = Channel;
/// let mut socket = Socket;
///
/// loop {
/// tokio::select! {
/// _ = read_send(&mut file, &mut channel) => { /* ... */ },
/// _data = socket.read_packet() => { /* ... */ }
/// _ = futures::future::ready(()) => break
/// }
/// loop {
/// tokio::select! {
/// _ = read_send(&mut file, &mut channel) => { /* ... */ },
/// _data = socket.read_packet() => { /* ... */ }
/// _ = futures::future::ready(()) => break
/// }
/// }
///
/// # }
/// ```
///
/// ### Moving to `merge`
@@ -487,32 +486,32 @@ macro_rules! doc {
/// Data(Vec<u8>),
/// }
///
/// #[tokio::main]
/// async fn main() {
/// // open our IO types
/// let file = File;
/// let channel = Channel;
/// let socket = Socket;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// // open our IO types
/// let file = File;
/// let channel = Channel;
/// let socket = Socket;
///
/// let a = unfold((file, channel), |(mut file, mut channel)| async {
/// read_send(&mut file, &mut channel).await;
/// Some((Message::Sent, (file, channel)))
/// });
/// let b = unfold(socket, |mut socket| async {
/// let data = socket.read_packet().await;
/// Some((Message::Data(data), socket))
/// });
/// let c = tokio_stream::iter([Message::Stop]);
/// let a = unfold((file, channel), |(mut file, mut channel)| async {
/// read_send(&mut file, &mut channel).await;
/// Some((Message::Sent, (file, channel)))
/// });
/// let b = unfold(socket, |mut socket| async {
/// let data = socket.read_packet().await;
/// Some((Message::Data(data), socket))
/// });
/// let c = tokio_stream::iter([Message::Stop]);
///
/// let mut s = pin!(a.merge(b).merge(c));
/// while let Some(msg) = s.next().await {
/// match msg {
/// Message::Data(_data) => { /* ... */ }
/// Message::Sent => continue,
/// Message::Stop => break,
/// }
/// let mut s = pin!(a.merge(b).merge(c));
/// while let Some(msg) = s.next().await {
/// match msg {
/// Message::Data(_data) => { /* ... */ }
/// Message::Sent => continue,
/// Message::Stop => break,
/// }
/// }
/// # }
/// ```
///
/// ## Racing Futures
@@ -533,17 +532,17 @@ macro_rules! doc {
/// ```
/// use futures_concurrency::future::Race;
///
/// #[tokio::main]
/// async fn main() {
/// let task_a = async { Ok("ok") };
/// let task_b = async { Err("error") };
/// let result = (task_a, task_b).race().await;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let task_a = async { Ok("ok") };
/// let task_b = async { Err("error") };
/// let result = (task_a, task_b).race().await;
///
/// match result {
/// Ok(output) => println!("First task completed with: {output}"),
/// Err(err) => eprintln!("Error occurred: {err}"),
/// }
/// match result {
/// Ok(output) => println!("First task completed with: {output}"),
/// Err(err) => eprintln!("Error occurred: {err}"),
/// }
/// # }
/// ```
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
+38 -38
View File
@@ -64,21 +64,21 @@ macro_rules! doc {
/// # Ok(())
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let res = tokio::try_join!(
/// do_stuff_async(),
/// more_async_work());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let res = tokio::try_join!(
/// do_stuff_async(),
/// more_async_work());
///
/// match res {
/// Ok((first, second)) => {
/// // do something with the values
/// }
/// Err(err) => {
/// println!("processing failed; error = {}", err);
/// }
/// match res {
/// Ok((first, second)) => {
/// // do something with the values
/// }
/// Err(err) => {
/// println!("processing failed; error = {}", err);
/// }
/// }
/// # }
/// ```
///
/// Using `try_join!` with spawned tasks.
@@ -104,20 +104,20 @@ macro_rules! doc {
/// }
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let handle1 = tokio::spawn(do_stuff_async());
/// let handle2 = tokio::spawn(more_async_work());
/// match tokio::try_join!(flatten(handle1), flatten(handle2)) {
/// Ok(val) => {
/// // do something with the values
/// }
/// Err(err) => {
/// println!("Failed with {}.", err);
/// # assert_eq!(err, "failed");
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let handle1 = tokio::spawn(do_stuff_async());
/// let handle2 = tokio::spawn(more_async_work());
/// match tokio::try_join!(flatten(handle1), flatten(handle2)) {
/// Ok(val) => {
/// // do something with the values
/// }
/// Err(err) => {
/// println!("Failed with {}.", err);
/// # assert_eq!(err, "failed");
/// }
/// }
/// # }
/// ```
/// Using the `biased;` mode to control polling order.
///
@@ -132,23 +132,23 @@ macro_rules! doc {
/// # Ok(())
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let res = tokio::try_join!(
/// biased;
/// do_stuff_async(),
/// more_async_work()
/// );
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let res = tokio::try_join!(
/// biased;
/// do_stuff_async(),
/// more_async_work()
/// );
///
/// match res {
/// Ok((first, second)) => {
/// // do something with the values
/// }
/// Err(err) => {
/// println!("processing failed; error = {}", err);
/// }
/// match res {
/// Ok((first, second)) => {
/// // do something with the values
/// }
/// Err(err) => {
/// println!("processing failed; error = {}", err);
/// }
/// }
/// # }
/// ```
#[macro_export]
#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
+78
View File
@@ -31,6 +31,8 @@ use std::time::Duration;
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Builder;
///
/// fn main() {
@@ -44,6 +46,7 @@ use std::time::Duration;
///
/// // use runtime ...
/// }
/// # }
/// ```
pub struct Builder {
/// Runtime type
@@ -152,6 +155,8 @@ cfg_unstable! {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::{self, UnhandledPanic};
///
/// # pub fn main() {
@@ -174,6 +179,7 @@ cfg_unstable! {
/// assert!(task2.await.is_ok());
/// })
/// # }
/// # }
/// ```
///
/// [`JoinHandle`]: struct@crate::task::JoinHandle
@@ -324,12 +330,15 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
///
/// let rt = runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap();
/// # }
/// ```
pub fn enable_all(&mut self) -> &mut Self {
#[cfg(any(
@@ -372,6 +381,8 @@ impl Builder {
/// ## Multi threaded runtime with 4 threads
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
///
/// // This will spawn a work-stealing runtime with 4 worker threads.
@@ -381,6 +392,7 @@ impl Builder {
/// .unwrap();
///
/// rt.spawn(async move {});
/// # }
/// ```
///
/// ## Current thread runtime (will only run on the current thread via `Runtime::block_on`)
@@ -466,6 +478,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
///
/// # pub fn main() {
@@ -473,6 +487,7 @@ impl Builder {
/// .thread_name("my-pool")
/// .build();
/// # }
/// # }
/// ```
pub fn thread_name(&mut self, val: impl Into<String>) -> &mut Self {
let val = val.into();
@@ -487,6 +502,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
/// # use std::sync::atomic::{AtomicUsize, Ordering};
/// # pub fn main() {
@@ -498,6 +515,7 @@ impl Builder {
/// })
/// .build();
/// # }
/// # }
/// ```
pub fn thread_name_fn<F>(&mut self, f: F) -> &mut Self
where
@@ -518,6 +536,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
///
/// # pub fn main() {
@@ -525,6 +545,7 @@ impl Builder {
/// .thread_stack_size(32 * 1024)
/// .build();
/// # }
/// # }
/// ```
pub fn thread_stack_size(&mut self, val: usize) -> &mut Self {
self.thread_stack_size = Some(val);
@@ -539,6 +560,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
/// # pub fn main() {
/// let runtime = runtime::Builder::new_multi_thread()
@@ -547,6 +570,7 @@ impl Builder {
/// })
/// .build();
/// # }
/// # }
/// ```
#[cfg(not(loom))]
pub fn on_thread_start<F>(&mut self, f: F) -> &mut Self
@@ -564,6 +588,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// {
/// # use tokio::runtime;
/// # pub fn main() {
/// let runtime = runtime::Builder::new_multi_thread()
@@ -572,6 +598,7 @@ impl Builder {
/// })
/// .build();
/// # }
/// # }
/// ```
#[cfg(not(loom))]
pub fn on_thread_stop<F>(&mut self, f: F) -> &mut Self
@@ -596,6 +623,8 @@ impl Builder {
///
/// ## Multithreaded executor
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use std::sync::Arc;
/// # use std::sync::atomic::{AtomicBool, Ordering};
/// # use tokio::runtime;
@@ -622,6 +651,7 @@ impl Builder {
/// barrier.wait().await;
/// })
/// # }
/// # }
/// ```
/// ## Current thread executor
/// ```
@@ -672,6 +702,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
/// # pub fn main() {
/// let runtime = runtime::Builder::new_multi_thread()
@@ -685,6 +717,7 @@ impl Builder {
/// println!("Hello from Tokio!");
/// })
/// # }
/// # }
/// ```
#[cfg(not(loom))]
pub fn on_thread_unpark<F>(&mut self, f: F) -> &mut Self
@@ -760,6 +793,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use std::sync::{atomic::AtomicUsize, Arc};
/// # use tokio::task::yield_now;
/// # pub fn main() {
@@ -778,6 +813,7 @@ impl Builder {
/// let _ = rt.block_on(task);
///
/// # }
/// # }
/// ```
#[cfg(tokio_unstable)]
#[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
@@ -804,6 +840,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use std::sync::{atomic::AtomicUsize, Arc};
/// # use tokio::task::yield_now;
/// # pub fn main() {
@@ -822,6 +860,7 @@ impl Builder {
/// let _ = rt.block_on(task);
///
/// # }
/// # }
/// ```
#[cfg(tokio_unstable)]
#[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
@@ -889,6 +928,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Builder;
///
/// let rt = Builder::new_multi_thread().build().unwrap();
@@ -896,6 +937,7 @@ impl Builder {
/// rt.block_on(async {
/// println!("Hello from the Tokio runtime");
/// });
/// # }
/// ```
pub fn build(&mut self) -> io::Result<Runtime> {
match &self.kind {
@@ -961,6 +1003,8 @@ impl Builder {
/// # Example
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
/// # use std::time::Duration;
/// # pub fn main() {
@@ -968,6 +1012,7 @@ impl Builder {
/// .thread_keep_alive(Duration::from_millis(100))
/// .build();
/// # }
/// # }
/// ```
pub fn thread_keep_alive(&mut self, duration: Duration) -> &mut Self {
self.keep_alive = Some(duration);
@@ -1000,12 +1045,15 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
/// # pub fn main() {
/// let rt = runtime::Builder::new_multi_thread()
/// .global_queue_interval(31)
/// .build();
/// # }
/// # }
/// ```
#[track_caller]
pub fn global_queue_interval(&mut self, val: u32) -> &mut Self {
@@ -1034,12 +1082,15 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use tokio::runtime;
/// # pub fn main() {
/// let rt = runtime::Builder::new_multi_thread()
/// .event_interval(31)
/// .build();
/// # }
/// # }
/// ```
pub fn event_interval(&mut self, val: u32) -> &mut Self {
self.event_interval = val;
@@ -1144,12 +1195,15 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
///
/// let rt = runtime::Builder::new_multi_thread()
/// .disable_lifo_slot()
/// .build()
/// .unwrap();
/// # }
/// ```
///
/// [tokio-rs/tokio-metrics]: https://github.com/tokio-rs/tokio-metrics
@@ -1214,6 +1268,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
///
/// let rt = runtime::Builder::new_multi_thread()
@@ -1226,6 +1282,7 @@ impl Builder {
/// # assert_eq!(m.poll_time_histogram_num_buckets(), 10);
/// # assert_eq!(m.poll_time_histogram_bucket_range(0), us(0)..us(100));
/// # assert_eq!(m.poll_time_histogram_bucket_range(1), us(100)..us(200));
/// # }
/// ```
///
/// [`Handle::metrics()`]: crate::runtime::Handle::metrics
@@ -1260,6 +1317,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::{self, HistogramScale};
///
/// # #[allow(deprecated)]
@@ -1268,6 +1327,7 @@ impl Builder {
/// .metrics_poll_count_histogram_scale(HistogramScale::Log)
/// .build()
/// .unwrap();
/// # }
/// ```
#[deprecated(note = "use `metrics_poll_time_histogram_configuration`")]
pub fn metrics_poll_count_histogram_scale(&mut self, histogram_scale: crate::runtime::HistogramScale) -> &mut Self {
@@ -1284,6 +1344,8 @@ impl Builder {
/// # Examples
/// Configure a [`LogHistogram`] with [default configuration]:
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
/// use tokio::runtime::{HistogramConfiguration, LogHistogram};
///
@@ -1294,10 +1356,13 @@ impl Builder {
/// )
/// .build()
/// .unwrap();
/// # }
/// ```
///
/// Configure a linear histogram with 100 buckets, each 10μs wide
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
/// use std::time::Duration;
/// use tokio::runtime::HistogramConfiguration;
@@ -1309,6 +1374,7 @@ impl Builder {
/// )
/// .build()
/// .unwrap();
/// # }
/// ```
///
/// Configure a [`LogHistogram`] with the following settings:
@@ -1316,6 +1382,8 @@ impl Builder {
/// - Max error of 0.1
/// - No more than 1024 buckets
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::time::Duration;
/// use tokio::runtime;
/// use tokio::runtime::{HistogramConfiguration, LogHistogram};
@@ -1333,6 +1401,7 @@ impl Builder {
/// )
/// .build()
/// .unwrap();
/// # }
/// ```
///
/// When migrating from the legacy histogram ([`HistogramScale::Log`]) and wanting
@@ -1382,6 +1451,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
/// use std::time::Duration;
///
@@ -1391,6 +1462,7 @@ impl Builder {
/// .metrics_poll_count_histogram_resolution(Duration::from_micros(100))
/// .build()
/// .unwrap();
/// # }
/// ```
#[deprecated(note = "use `metrics_poll_time_histogram_configuration`")]
pub fn metrics_poll_count_histogram_resolution(&mut self, resolution: Duration) -> &mut Self {
@@ -1417,6 +1489,8 @@ impl Builder {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
///
/// # #[allow(deprecated)]
@@ -1425,6 +1499,7 @@ impl Builder {
/// .metrics_poll_count_histogram_buckets(15)
/// .build()
/// .unwrap();
/// # }
/// ```
#[deprecated(note = "use `metrics_poll_time_histogram_configuration`")]
pub fn metrics_poll_count_histogram_buckets(&mut self, buckets: usize) -> &mut Self {
@@ -1576,12 +1651,15 @@ cfg_time! {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime;
///
/// let rt = runtime::Builder::new_multi_thread()
/// .enable_time()
/// .build()
/// .unwrap();
/// # }
/// ```
pub fn enable_time(&mut self) -> &mut Self {
self.enable_time = true;
+23 -1
View File
@@ -52,6 +52,8 @@ impl Handle {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// let rt = Runtime::new().unwrap();
@@ -60,12 +62,13 @@ impl Handle {
/// tokio::spawn(async {
/// println!("Hello world!");
/// });
/// # }
/// ```
///
/// Do **not** do the following, this shows a scenario that will result in a
/// panic and possible memory leak.
///
/// ```should_panic
/// ```should_panic,ignore-wasm
/// use tokio::runtime::Runtime;
///
/// let rt1 = Runtime::new().unwrap();
@@ -106,6 +109,8 @@ impl Handle {
/// block or function running on that runtime.
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// # use std::thread;
/// # use tokio::runtime::Runtime;
/// # fn dox() {
@@ -134,6 +139,7 @@ impl Handle {
/// # handle.join().unwrap();
/// # });
/// # }
/// # }
/// ```
#[track_caller]
pub fn current() -> Self {
@@ -170,6 +176,8 @@ impl Handle {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
@@ -183,6 +191,7 @@ impl Handle {
/// println!("now running on a worker thread");
/// });
/// # }
/// # }
/// ```
#[track_caller]
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
@@ -204,6 +213,8 @@ impl Handle {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
@@ -217,6 +228,8 @@ impl Handle {
/// println!("now running on a worker thread");
/// });
/// # }
/// # }
/// ```
#[track_caller]
pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
where
@@ -256,6 +269,8 @@ impl Handle {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// // Create the runtime
@@ -268,11 +283,14 @@ impl Handle {
/// handle.block_on(async {
/// println!("hello");
/// });
/// # }
/// ```
///
/// Or using `Handle::current`:
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
@@ -285,6 +303,7 @@ impl Handle {
/// });
/// });
/// }
/// # }
/// ```
///
/// [`JoinError`]: struct@crate::task::JoinError
@@ -387,12 +406,15 @@ impl Handle {
/// ```
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::{Handle, RuntimeFlavor};
///
/// #[tokio::main(flavor = "multi_thread", worker_threads = 4)]
/// async fn main() {
/// assert_eq!(RuntimeFlavor::MultiThread, Handle::current().runtime_flavor());
/// }
/// # }
/// ```
pub fn runtime_flavor(&self) -> RuntimeFlavor {
match self.inner {
+3
View File
@@ -16,12 +16,15 @@ use std::num::{NonZeroU32, NonZeroU64};
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Handle;
///
/// #[tokio::main(flavor = "multi_thread", worker_threads = 4)]
/// async fn main() {
/// println!("Current runtime id: {}", Handle::current().id());
/// }
/// # }
/// ```
///
/// **Note**: This is an [unstable API][unstable]. The public API of this type
@@ -313,6 +313,8 @@ impl LocalRuntime {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::LocalRuntime;
/// use tokio::task;
///
@@ -330,6 +332,7 @@ impl LocalRuntime {
///
/// runtime.shutdown_timeout(Duration::from_millis(100));
/// }
/// # }
/// ```
pub fn shutdown_timeout(mut self, duration: Duration) {
// Wakeup and shutdown all the worker threads
+128 -122
View File
@@ -37,13 +37,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.num_workers();
/// println!("Runtime is using {} workers", n);
/// }
/// let n = metrics.num_workers();
/// println!("Runtime is using {} workers", n);
/// # }
/// ```
pub fn num_workers(&self) -> usize {
self.handle.inner.num_workers()
@@ -59,13 +59,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.num_alive_tasks();
/// println!("Runtime has {} alive tasks", n);
/// }
/// let n = metrics.num_alive_tasks();
/// println!("Runtime has {} alive tasks", n);
/// # }
/// ```
pub fn num_alive_tasks(&self) -> usize {
self.handle.inner.num_alive_tasks()
@@ -85,13 +85,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.global_queue_depth();
/// println!("{} tasks currently pending in the runtime's global queue", n);
/// }
/// let n = metrics.global_queue_depth();
/// println!("{} tasks currently pending in the runtime's global queue", n);
/// # }
/// ```
pub fn global_queue_depth(&self) -> usize {
self.handle.inner.injection_queue_depth()
@@ -126,13 +126,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_total_busy_duration(0);
/// println!("worker 0 was busy for a total of {:?}", n);
/// }
/// let n = metrics.worker_total_busy_duration(0);
/// println!("worker 0 was busy for a total of {:?}", n);
/// # }
/// ```
pub fn worker_total_busy_duration(&self, worker: usize) -> Duration {
let nanos = self
@@ -171,13 +171,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_park_count(0);
/// println!("worker 0 parked {} times", n);
/// }
/// let n = metrics.worker_park_count(0);
/// println!("worker 0 parked {} times", n);
/// # }
/// ```
pub fn worker_park_count(&self, worker: usize) -> u64 {
self.handle
@@ -219,19 +219,19 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// let n = metrics.worker_park_unpark_count(0);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
/// let n = metrics.worker_park_unpark_count(0);
///
/// println!("worker 0 parked and unparked {} times", n);
/// println!("worker 0 parked and unparked {} times", n);
///
/// if n % 2 == 0 {
/// println!("worker 0 is active");
/// } else {
/// println!("worker 0 is parked");
/// }
/// if n % 2 == 0 {
/// println!("worker 0 is active");
/// } else {
/// println!("worker 0 is parked");
/// }
/// # }
/// ```
pub fn worker_park_unpark_count(&self, worker: usize) -> u64 {
self.handle
@@ -252,19 +252,22 @@ impl RuntimeMetrics {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let _ = tokio::task::spawn_blocking(move || {
/// // Stand-in for compute-heavy work or using synchronous APIs
/// 1 + 1
/// }).await;
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let _ = tokio::task::spawn_blocking(move || {
/// // Stand-in for compute-heavy work or using synchronous APIs
/// 1 + 1
/// }).await;
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.num_blocking_threads();
/// println!("Runtime has created {} threads", n);
/// }
/// let n = metrics.num_blocking_threads();
/// println!("Runtime has created {} threads", n);
/// # }
/// # }
/// ```
pub fn num_blocking_threads(&self) -> usize {
self.handle.inner.num_blocking_threads()
@@ -282,6 +285,8 @@ impl RuntimeMetrics {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
@@ -295,6 +300,7 @@ impl RuntimeMetrics {
/// let n = metrics.num_idle_blocking_threads();
/// println!("Runtime has {} idle blocking thread pool threads", n);
/// }
/// # }
/// ```
pub fn num_idle_blocking_threads(&self) -> usize {
self.handle.inner.num_idle_blocking_threads()
@@ -328,13 +334,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let id = metrics.worker_thread_id(0);
/// println!("worker 0 has id {:?}", id);
/// }
/// let id = metrics.worker_thread_id(0);
/// println!("worker 0 has id {:?}", id);
/// # }
/// ```
pub fn worker_thread_id(&self, worker: usize) -> Option<ThreadId> {
self.handle
@@ -376,13 +382,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_local_queue_depth(0);
/// println!("{} tasks currently pending in worker 0's local queue", n);
/// }
/// let n = metrics.worker_local_queue_depth(0);
/// println!("{} tasks currently pending in worker 0's local queue", n);
/// # }
/// ```
pub fn worker_local_queue_depth(&self, worker: usize) -> usize {
self.handle.inner.worker_local_queue_depth(worker)
@@ -550,13 +556,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.blocking_queue_depth();
/// println!("{} tasks currently pending in the blocking thread pool", n);
/// }
/// let n = metrics.blocking_queue_depth();
/// println!("{} tasks currently pending in the blocking thread pool", n);
/// # }
/// ```
pub fn blocking_queue_depth(&self) -> usize {
self.handle.inner.blocking_queue_depth()
@@ -580,13 +586,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.spawned_tasks_count();
/// println!("Runtime has had {} tasks spawned", n);
/// }
/// let n = metrics.spawned_tasks_count();
/// println!("Runtime has had {} tasks spawned", n);
/// # }
/// ```
pub fn spawned_tasks_count(&self) -> u64 {
self.handle.inner.spawned_tasks_count()
@@ -608,13 +614,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.remote_schedule_count();
/// println!("{} tasks were scheduled from outside the runtime", n);
/// }
/// let n = metrics.remote_schedule_count();
/// println!("{} tasks were scheduled from outside the runtime", n);
/// # }
/// ```
pub fn remote_schedule_count(&self) -> u64 {
self.handle
@@ -666,13 +672,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_noop_count(0);
/// println!("worker 0 had {} no-op unparks", n);
/// }
/// let n = metrics.worker_noop_count(0);
/// println!("worker 0 had {} no-op unparks", n);
/// # }
/// ```
pub fn worker_noop_count(&self, worker: usize) -> u64 {
self.handle
@@ -712,13 +718,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_steal_count(0);
/// println!("worker 0 has stolen {} tasks", n);
/// }
/// let n = metrics.worker_steal_count(0);
/// println!("worker 0 has stolen {} tasks", n);
/// # }
/// ```
pub fn worker_steal_count(&self, worker: usize) -> u64 {
self.handle
@@ -758,13 +764,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_steal_operations(0);
/// println!("worker 0 has stolen tasks {} times", n);
/// }
/// let n = metrics.worker_steal_operations(0);
/// println!("worker 0 has stolen tasks {} times", n);
/// # }
/// ```
pub fn worker_steal_operations(&self, worker: usize) -> u64 {
self.handle
@@ -799,13 +805,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_poll_count(0);
/// println!("worker 0 has polled {} tasks", n);
/// }
/// let n = metrics.worker_poll_count(0);
/// println!("worker 0 has polled {} tasks", n);
/// # }
/// ```
pub fn worker_poll_count(&self, worker: usize) -> u64 {
self.handle
@@ -844,13 +850,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_local_schedule_count(0);
/// println!("{} tasks were scheduled on the worker's local queue", n);
/// }
/// let n = metrics.worker_local_schedule_count(0);
/// println!("{} tasks were scheduled on the worker's local queue", n);
/// # }
/// ```
pub fn worker_local_schedule_count(&self, worker: usize) -> u64 {
self.handle
@@ -890,13 +896,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_overflow_count(0);
/// println!("worker 0 has overflowed its queue {} times", n);
/// }
/// let n = metrics.worker_overflow_count(0);
/// println!("worker 0 has overflowed its queue {} times", n);
/// # }
/// ```
pub fn worker_overflow_count(&self, worker: usize) -> u64 {
self.handle
@@ -999,13 +1005,13 @@ impl RuntimeMetrics {
/// ```
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// async fn main() {
/// let metrics = Handle::current().metrics();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let metrics = Handle::current().metrics();
///
/// let n = metrics.worker_mean_poll_time(0);
/// println!("worker 0 has a mean poll time of {:?}", n);
/// }
/// let n = metrics.worker_mean_poll_time(0);
/// println!("worker 0 has a mean poll time of {:?}", n);
/// # }
/// ```
#[track_caller]
pub fn worker_mean_poll_time(&self, worker: usize) -> Duration {
+9
View File
@@ -19,6 +19,8 @@
//! used.
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::net::TcpListener;
//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
//!
@@ -53,6 +55,7 @@
//! });
//! }
//! }
//! # }
//! ```
//!
//! From within the context of the runtime, additional tasks are spawned using
@@ -62,6 +65,8 @@
//! A [`Runtime`] instance can also be used directly.
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::net::TcpListener;
//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
//! use tokio::runtime::Runtime;
@@ -102,6 +107,7 @@
//! }
//! })
//! }
//! # }
//! ```
//!
//! ## Runtime Configurations
@@ -118,11 +124,14 @@
//! for most applications. The multi-thread scheduler requires the `rt-multi-thread`
//! feature flag, and is selected by default:
//! ```
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::runtime;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let threaded_rt = runtime::Runtime::new()?;
//! # Ok(()) }
//! # }
//! ```
//!
//! Most applications should use the multi-thread scheduler, except in some
+21
View File
@@ -184,6 +184,8 @@ impl Runtime {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// let rt = Runtime::new()
@@ -192,6 +194,7 @@ impl Runtime {
/// let handle = rt.handle();
///
/// // Use the handle...
/// # }
/// ```
pub fn handle(&self) -> &Handle {
&self.handle
@@ -214,6 +217,8 @@ impl Runtime {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
@@ -225,6 +230,7 @@ impl Runtime {
/// println!("now running on a worker thread");
/// });
/// # }
/// # }
/// ```
#[track_caller]
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
@@ -247,6 +253,8 @@ impl Runtime {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
@@ -258,6 +266,7 @@ impl Runtime {
/// println!("now running on a worker thread");
/// });
/// # }
/// # }
/// ```
#[track_caller]
pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
@@ -309,6 +318,8 @@ impl Runtime {
/// # Examples
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// // Create the runtime
@@ -318,6 +329,7 @@ impl Runtime {
/// rt.block_on(async {
/// println!("hello");
/// });
/// # }
/// ```
///
/// [handle]: fn@Handle::block_on
@@ -372,6 +384,8 @@ impl Runtime {
/// # Example
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
/// use tokio::task::JoinHandle;
///
@@ -394,6 +408,7 @@ impl Runtime {
/// // Wait for the task before we end the test.
/// rt.block_on(handle).unwrap();
/// }
/// # }
/// ```
pub fn enter(&self) -> EnterGuard<'_> {
self.handle.enter()
@@ -407,6 +422,8 @@ impl Runtime {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
/// use tokio::task;
///
@@ -425,6 +442,7 @@ impl Runtime {
///
/// runtime.shutdown_timeout(Duration::from_millis(100));
/// }
/// # }
/// ```
pub fn shutdown_timeout(mut self, duration: Duration) {
// Wakeup and shutdown all the worker threads
@@ -448,6 +466,8 @@ impl Runtime {
/// This function is equivalent to calling `shutdown_timeout(Duration::from_nanos(0))`.
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
///
/// fn main() {
@@ -459,6 +479,7 @@ impl Runtime {
/// inner_runtime.shutdown_background();
/// });
/// }
/// # }
/// ```
pub fn shutdown_background(self) {
self.shutdown_timeout(Duration::from_nanos(0));
+5 -2
View File
@@ -46,6 +46,8 @@ impl JoinError {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::panic;
///
/// #[tokio::main]
@@ -56,6 +58,7 @@ impl JoinError {
///
/// assert!(err.is_panic());
/// }
/// # }
/// ```
pub fn is_panic(&self) -> bool {
matches!(&self.repr, Repr::Panic(_))
@@ -71,7 +74,7 @@ impl JoinError {
///
/// # Examples
///
/// ```should_panic
/// ```should_panic,ignore-wasm
/// use std::panic;
///
/// #[tokio::main]
@@ -98,7 +101,7 @@ impl JoinError {
///
/// # Examples
///
/// ```should_panic
/// ```should_panic,ignore-wasm
/// use std::panic;
///
/// #[tokio::main]
+14 -11
View File
@@ -91,21 +91,23 @@ cfg_rt! {
/// use tokio::task;
/// use std::io;
///
/// #[tokio::main]
/// async fn main() -> io::Result<()> {
/// let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
/// Ok(5 + 3)
/// });
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> io::Result<()> {
/// let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
/// Ok(5 + 3)
/// });
///
/// let result = join_handle.await??;
/// assert_eq!(result, 8);
/// Ok(())
/// }
/// let result = join_handle.await??;
/// assert_eq!(result, 8);
/// Ok(())
/// # }
/// ```
///
/// If the task panics, the error is a [`JoinError`] that contains the panic:
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::task;
/// use std::io;
/// use std::panic;
@@ -120,7 +122,7 @@ cfg_rt! {
/// assert!(err.is_panic());
/// Ok(())
/// }
///
/// # }
/// ```
/// Child being detached and outliving its parent:
///
@@ -129,7 +131,8 @@ cfg_rt! {
/// use tokio::time;
/// use std::time::Duration;
///
/// # #[tokio::main] async fn main() {
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let original_task = task::spawn(async {
/// let _detached_task = task::spawn(async {
/// // Here we sleep to make sure that the first task returns before.
+1 -1
View File
@@ -6,7 +6,7 @@ use crate::util::trace;
/// A barrier enables multiple tasks to synchronize the beginning of some computation.
///
/// ```
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio::sync::Barrier;
/// use std::sync::Arc;
+246 -243
View File
@@ -73,24 +73,24 @@
//! ```
//! use tokio::sync::broadcast;
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, mut rx1) = broadcast::channel(16);
//! let mut rx2 = tx.subscribe();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, mut rx1) = broadcast::channel(16);
//! let mut rx2 = tx.subscribe();
//!
//! tokio::spawn(async move {
//! assert_eq!(rx1.recv().await.unwrap(), 10);
//! assert_eq!(rx1.recv().await.unwrap(), 20);
//! });
//! tokio::spawn(async move {
//! assert_eq!(rx1.recv().await.unwrap(), 10);
//! assert_eq!(rx1.recv().await.unwrap(), 20);
//! });
//!
//! tokio::spawn(async move {
//! assert_eq!(rx2.recv().await.unwrap(), 10);
//! assert_eq!(rx2.recv().await.unwrap(), 20);
//! });
//! tokio::spawn(async move {
//! assert_eq!(rx2.recv().await.unwrap(), 10);
//! assert_eq!(rx2.recv().await.unwrap(), 20);
//! });
//!
//! tx.send(10).unwrap();
//! tx.send(20).unwrap();
//! }
//! tx.send(10).unwrap();
//! tx.send(20).unwrap();
//! # }
//! ```
//!
//! Handling lag
@@ -98,22 +98,22 @@
//! ```
//! use tokio::sync::broadcast;
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, mut rx) = broadcast::channel(2);
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, mut rx) = broadcast::channel(2);
//!
//! tx.send(10).unwrap();
//! tx.send(20).unwrap();
//! tx.send(30).unwrap();
//! tx.send(10).unwrap();
//! tx.send(20).unwrap();
//! tx.send(30).unwrap();
//!
//! // The receiver lagged behind
//! assert!(rx.recv().await.is_err());
//! // The receiver lagged behind
//! assert!(rx.recv().await.is_err());
//!
//! // At this point, we can abort or continue with lost messages
//! // At this point, we can abort or continue with lost messages
//!
//! assert_eq!(20, rx.recv().await.unwrap());
//! assert_eq!(30, rx.recv().await.unwrap());
//! }
//! assert_eq!(20, rx.recv().await.unwrap());
//! assert_eq!(30, rx.recv().await.unwrap());
//! # }
//! ```
use crate::loom::cell::UnsafeCell;
@@ -141,24 +141,24 @@ use std::task::{ready, Context, Poll, Waker};
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
///
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// }
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// # }
/// ```
///
/// [`broadcast`]: crate::sync::broadcast
@@ -183,18 +183,18 @@ pub struct Sender<T> {
/// ```
/// use tokio::sync::broadcast::channel;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx) = channel::<i32>(15);
/// let tx_weak = tx.downgrade();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx) = channel::<i32>(15);
/// let tx_weak = tx.downgrade();
///
/// // Upgrading will succeed because `tx` still exists.
/// assert!(tx_weak.upgrade().is_some());
/// // Upgrading will succeed because `tx` still exists.
/// assert!(tx_weak.upgrade().is_some());
///
/// // If we drop `tx`, then it will fail.
/// drop(tx);
/// assert!(tx_weak.clone().upgrade().is_none());
/// }
/// // If we drop `tx`, then it will fail.
/// drop(tx);
/// assert!(tx_weak.clone().upgrade().is_none());
/// # }
/// ```
pub struct WeakSender<T> {
shared: Arc<Shared<T>>,
@@ -215,24 +215,24 @@ pub struct WeakSender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
///
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// }
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// # }
/// ```
///
/// [`broadcast`]: crate::sync::broadcast
@@ -478,24 +478,24 @@ const MAX_RECEIVERS: usize = usize::MAX >> 2;
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
///
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// }
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// # }
/// ```
///
/// # Panics
@@ -609,24 +609,24 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
///
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// }
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// # }
/// ```
pub fn send(&self, value: T) -> Result<usize, SendError<T>> {
let mut tail = self.shared.tail.lock();
@@ -674,20 +674,20 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx) = broadcast::channel(16);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx) = broadcast::channel(16);
///
/// // Will not be seen
/// tx.send(10).unwrap();
/// // Will not be seen
/// tx.send(10).unwrap();
///
/// let mut rx = tx.subscribe();
/// let mut rx = tx.subscribe();
///
/// tx.send(20).unwrap();
/// tx.send(20).unwrap();
///
/// let value = rx.recv().await.unwrap();
/// assert_eq!(20, value);
/// }
/// let value = rx.recv().await.unwrap();
/// assert_eq!(20, value);
/// # }
/// ```
pub fn subscribe(&self) -> Receiver<T> {
let shared = self.shared.clone();
@@ -722,26 +722,26 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// tx.send(30).unwrap();
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// tx.send(30).unwrap();
///
/// assert_eq!(tx.len(), 3);
/// assert_eq!(tx.len(), 3);
///
/// rx1.recv().await.unwrap();
/// rx1.recv().await.unwrap();
///
/// // The len is still 3 since rx2 hasn't seen the first value yet.
/// assert_eq!(tx.len(), 3);
/// // The len is still 3 since rx2 hasn't seen the first value yet.
/// assert_eq!(tx.len(), 3);
///
/// rx2.recv().await.unwrap();
/// rx2.recv().await.unwrap();
///
/// assert_eq!(tx.len(), 2);
/// }
/// assert_eq!(tx.len(), 2);
/// # }
/// ```
pub fn len(&self) -> usize {
let tail = self.shared.tail.lock();
@@ -769,26 +769,26 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// assert!(tx.is_empty());
/// assert!(tx.is_empty());
///
/// tx.send(10).unwrap();
/// tx.send(10).unwrap();
///
/// assert!(!tx.is_empty());
/// assert!(!tx.is_empty());
///
/// rx1.recv().await.unwrap();
/// rx1.recv().await.unwrap();
///
/// // The queue is still not empty since rx2 hasn't seen the value.
/// assert!(!tx.is_empty());
/// // The queue is still not empty since rx2 hasn't seen the value.
/// assert!(!tx.is_empty());
///
/// rx2.recv().await.unwrap();
/// rx2.recv().await.unwrap();
///
/// assert!(tx.is_empty());
/// }
/// assert!(tx.is_empty());
/// # }
/// ```
pub fn is_empty(&self) -> bool {
let tail = self.shared.tail.lock();
@@ -820,18 +820,18 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx1) = broadcast::channel(16);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx1) = broadcast::channel(16);
///
/// assert_eq!(1, tx.receiver_count());
/// assert_eq!(1, tx.receiver_count());
///
/// let mut _rx2 = tx.subscribe();
/// let mut _rx2 = tx.subscribe();
///
/// assert_eq!(2, tx.receiver_count());
/// assert_eq!(2, tx.receiver_count());
///
/// tx.send(10).unwrap();
/// }
/// tx.send(10).unwrap();
/// # }
/// ```
pub fn receiver_count(&self) -> usize {
let tail = self.shared.tail.lock();
@@ -845,17 +845,17 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx) = broadcast::channel::<()>(16);
/// let tx2 = tx.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx) = broadcast::channel::<()>(16);
/// let tx2 = tx.clone();
///
/// assert!(tx.same_channel(&tx2));
/// assert!(tx.same_channel(&tx2));
///
/// let (tx3, _rx3) = broadcast::channel::<()>(16);
/// let (tx3, _rx3) = broadcast::channel::<()>(16);
///
/// assert!(!tx3.same_channel(&tx2));
/// }
/// assert!(!tx3.same_channel(&tx2));
/// # }
/// ```
pub fn same_channel(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.shared, &other.shared)
@@ -870,21 +870,21 @@ impl<T> Sender<T> {
/// use futures::FutureExt;
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel::<u32>(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel::<u32>(16);
/// let mut rx2 = tx.subscribe();
///
/// let _ = tx.send(10);
/// let _ = tx.send(10);
///
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// drop(rx1);
/// assert!(tx.closed().now_or_never().is_none());
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// drop(rx1);
/// assert!(tx.closed().now_or_never().is_none());
///
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// drop(rx2);
/// assert!(tx.closed().now_or_never().is_some());
/// }
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// drop(rx2);
/// assert!(tx.closed().now_or_never().is_some());
/// # }
/// ```
pub async fn closed(&self) {
loop {
@@ -1148,19 +1148,19 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
///
/// assert_eq!(rx1.len(), 2);
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.len(), 1);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// assert_eq!(rx1.len(), 0);
/// }
/// assert_eq!(rx1.len(), 2);
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.len(), 1);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// assert_eq!(rx1.len(), 0);
/// # }
/// ```
pub fn len(&self) -> usize {
let next_send_pos = self.shared.tail.lock().pos;
@@ -1177,20 +1177,20 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
///
/// assert!(rx1.is_empty());
/// assert!(rx1.is_empty());
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
///
/// assert!(!rx1.is_empty());
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// assert!(rx1.is_empty());
/// }
/// assert!(!rx1.is_empty());
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// assert!(rx1.is_empty());
/// # }
/// ```
pub fn is_empty(&self) -> bool {
self.len() == 0
@@ -1203,17 +1203,17 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = broadcast::channel::<()>(16);
/// let rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = broadcast::channel::<()>(16);
/// let rx2 = tx.subscribe();
///
/// assert!(rx.same_channel(&rx2));
/// assert!(rx.same_channel(&rx2));
///
/// let (_tx3, rx3) = broadcast::channel::<()>(16);
/// let (_tx3, rx3) = broadcast::channel::<()>(16);
///
/// assert!(!rx3.same_channel(&rx2));
/// }
/// assert!(!rx3.same_channel(&rx2));
/// # }
/// ```
pub fn same_channel(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.shared, &other.shared)
@@ -1348,15 +1348,15 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = broadcast::channel::<()>(10);
/// assert!(!rx.is_closed());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = broadcast::channel::<()>(10);
/// assert!(!rx.is_closed());
///
/// drop(tx);
/// drop(tx);
///
/// assert!(rx.is_closed());
/// }
/// assert!(rx.is_closed());
/// # }
/// ```
pub fn is_closed(&self) -> bool {
// Channel is closed when there are no strong senders left active
@@ -1376,17 +1376,17 @@ impl<T: Clone> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = broadcast::channel(2);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = broadcast::channel(2);
///
/// tx.send(1).unwrap();
/// let mut rx2 = rx.resubscribe();
/// tx.send(2).unwrap();
/// tx.send(1).unwrap();
/// let mut rx2 = rx.resubscribe();
/// tx.send(2).unwrap();
///
/// assert_eq!(rx2.recv().await.unwrap(), 2);
/// assert_eq!(rx.recv().await.unwrap(), 1);
/// }
/// assert_eq!(rx2.recv().await.unwrap(), 2);
/// assert_eq!(rx.recv().await.unwrap(), 1);
/// # }
/// ```
pub fn resubscribe(&self) -> Self {
let shared = self.shared.clone();
@@ -1422,24 +1422,24 @@ impl<T: Clone> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx1) = broadcast::channel(16);
/// let mut rx2 = tx.subscribe();
///
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx1.recv().await.unwrap(), 10);
/// assert_eq!(rx1.recv().await.unwrap(), 20);
/// });
///
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
/// tokio::spawn(async move {
/// assert_eq!(rx2.recv().await.unwrap(), 10);
/// assert_eq!(rx2.recv().await.unwrap(), 20);
/// });
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// }
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// # }
/// ```
///
/// Handling lag
@@ -1447,22 +1447,22 @@ impl<T: Clone> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = broadcast::channel(2);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = broadcast::channel(2);
///
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// tx.send(30).unwrap();
/// tx.send(10).unwrap();
/// tx.send(20).unwrap();
/// tx.send(30).unwrap();
///
/// // The receiver lagged behind
/// assert!(rx.recv().await.is_err());
/// // The receiver lagged behind
/// assert!(rx.recv().await.is_err());
///
/// // At this point, we can abort or continue with lost messages
/// // At this point, we can abort or continue with lost messages
///
/// assert_eq!(20, rx.recv().await.unwrap());
/// assert_eq!(30, rx.recv().await.unwrap());
/// }
/// assert_eq!(20, rx.recv().await.unwrap());
/// assert_eq!(30, rx.recv().await.unwrap());
/// # }
/// ```
pub async fn recv(&mut self) -> Result<T, RecvError> {
cooperative(Recv::new(self)).await
@@ -1496,17 +1496,17 @@ impl<T: Clone> Receiver<T> {
/// ```
/// use tokio::sync::broadcast;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = broadcast::channel(16);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = broadcast::channel(16);
///
/// assert!(rx.try_recv().is_err());
/// assert!(rx.try_recv().is_err());
///
/// tx.send(10).unwrap();
/// tx.send(10).unwrap();
///
/// let value = rx.try_recv().unwrap();
/// assert_eq!(10, value);
/// }
/// let value = rx.try_recv().unwrap();
/// assert_eq!(10, value);
/// # }
/// ```
pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
let guard = self.recv_ref(None)?;
@@ -1522,6 +1522,8 @@ impl<T: Clone> Receiver<T> {
///
/// # Examples
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::thread;
/// use tokio::sync::broadcast;
///
@@ -1536,6 +1538,7 @@ impl<T: Clone> Receiver<T> {
/// let _ = tx.send(10);
/// sync_code.join().unwrap();
/// }
/// # }
/// ```
pub fn blocking_recv(&mut self) -> Result<T, RecvError> {
crate::future::block_on(self.recv())
+159 -156
View File
@@ -42,20 +42,20 @@
//! "represents the result of the computation".to_string()
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, rx) = oneshot::channel();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, rx) = oneshot::channel();
//!
//! tokio::spawn(async move {
//! let res = some_computation().await;
//! tx.send(res).unwrap();
//! });
//! tokio::spawn(async move {
//! let res = some_computation().await;
//! tx.send(res).unwrap();
//! });
//!
//! // Do other work while the computation is happening in the background
//! // Do other work while the computation is happening in the background
//!
//! // Wait for the computation result
//! let res = rx.await.unwrap();
//! }
//! // Wait for the computation result
//! let res = rx.await.unwrap();
//! # }
//! ```
//!
//! Note, if the task produces a computation result as its final
@@ -72,17 +72,17 @@
//! "the result of the computation".to_string()
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let join_handle = tokio::spawn(async move {
//! some_computation().await
//! });
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let join_handle = tokio::spawn(async move {
//! some_computation().await
//! });
//!
//! // Do other work while the computation is happening in the background
//! // Do other work while the computation is happening in the background
//!
//! // Wait for the computation result
//! let res = join_handle.await.unwrap();
//! }
//! // Wait for the computation result
//! let res = join_handle.await.unwrap();
//! # }
//! ```
//!
//! [`JoinHandle`]: crate::task::JoinHandle
@@ -107,21 +107,21 @@
//! format!("the result of computation {}", input)
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, mut rx) = mpsc::channel(100);
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, mut rx) = mpsc::channel(100);
//!
//! tokio::spawn(async move {
//! for i in 0..10 {
//! let res = some_computation(i).await;
//! tx.send(res).await.unwrap();
//! }
//! });
//!
//! while let Some(res) = rx.recv().await {
//! println!("got = {}", res);
//! tokio::spawn(async move {
//! for i in 0..10 {
//! let res = some_computation(i).await;
//! tx.send(res).await.unwrap();
//! }
//! });
//!
//! while let Some(res) = rx.recv().await {
//! println!("got = {}", res);
//! }
//! # }
//! ```
//!
//! The argument to `mpsc::channel` is the channel capacity. This is the maximum
@@ -141,6 +141,8 @@
//! passing.
//!
//! ```no_run
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::io::{self, AsyncWriteExt};
//! use tokio::net::TcpStream;
//! use tokio::sync::mpsc;
@@ -172,6 +174,7 @@
//!
//! Ok(())
//! }
//! # }
//! ```
//!
//! The [`mpsc`] and [`oneshot`] channels can be combined to provide a request /
@@ -193,46 +196,46 @@
//! // Other commands can be added here
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let (cmd_tx, mut cmd_rx) = mpsc::channel::<(Command, oneshot::Sender<u64>)>(100);
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (cmd_tx, mut cmd_rx) = mpsc::channel::<(Command, oneshot::Sender<u64>)>(100);
//!
//! // Spawn a task to manage the counter
//! tokio::spawn(async move {
//! let mut counter: u64 = 0;
//! // Spawn a task to manage the counter
//! tokio::spawn(async move {
//! let mut counter: u64 = 0;
//!
//! while let Some((cmd, response)) = cmd_rx.recv().await {
//! match cmd {
//! Increment => {
//! let prev = counter;
//! counter += 1;
//! response.send(prev).unwrap();
//! }
//! while let Some((cmd, response)) = cmd_rx.recv().await {
//! match cmd {
//! Increment => {
//! let prev = counter;
//! counter += 1;
//! response.send(prev).unwrap();
//! }
//! }
//! });
//!
//! let mut join_handles = vec![];
//!
//! // Spawn tasks that will send the increment command.
//! for _ in 0..10 {
//! let cmd_tx = cmd_tx.clone();
//!
//! join_handles.push(tokio::spawn(async move {
//! let (resp_tx, resp_rx) = oneshot::channel();
//!
//! cmd_tx.send((Increment, resp_tx)).await.ok().unwrap();
//! let res = resp_rx.await.unwrap();
//!
//! println!("previous value = {}", res);
//! }));
//! }
//! });
//!
//! // Wait for all tasks to complete
//! for join_handle in join_handles.drain(..) {
//! join_handle.await.unwrap();
//! }
//! let mut join_handles = vec![];
//!
//! // Spawn tasks that will send the increment command.
//! for _ in 0..10 {
//! let cmd_tx = cmd_tx.clone();
//!
//! join_handles.push(tokio::spawn(async move {
//! let (resp_tx, resp_rx) = oneshot::channel();
//!
//! cmd_tx.send((Increment, resp_tx)).await.ok().unwrap();
//! let res = resp_rx.await.unwrap();
//!
//! println!("previous value = {}", res);
//! }));
//! }
//!
//! // Wait for all tasks to complete
//! for join_handle in join_handles.drain(..) {
//! join_handle.await.unwrap();
//! }
//! # }
//! ```
//!
//! ## `broadcast` channel
@@ -254,24 +257,24 @@
//! ```
//! use tokio::sync::broadcast;
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, mut rx1) = broadcast::channel(16);
//! let mut rx2 = tx.subscribe();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, mut rx1) = broadcast::channel(16);
//! let mut rx2 = tx.subscribe();
//!
//! tokio::spawn(async move {
//! assert_eq!(rx1.recv().await.unwrap(), 10);
//! assert_eq!(rx1.recv().await.unwrap(), 20);
//! });
//! tokio::spawn(async move {
//! assert_eq!(rx1.recv().await.unwrap(), 10);
//! assert_eq!(rx1.recv().await.unwrap(), 20);
//! });
//!
//! tokio::spawn(async move {
//! assert_eq!(rx2.recv().await.unwrap(), 10);
//! assert_eq!(rx2.recv().await.unwrap(), 20);
//! });
//! tokio::spawn(async move {
//! assert_eq!(rx2.recv().await.unwrap(), 10);
//! assert_eq!(rx2.recv().await.unwrap(), 20);
//! });
//!
//! tx.send(10).unwrap();
//! tx.send(20).unwrap();
//! }
//! tx.send(10).unwrap();
//! tx.send(20).unwrap();
//! # }
//! ```
//!
//! [`broadcast` channel]: crate::sync::broadcast
@@ -315,92 +318,92 @@
//! // Do something here
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! // Load initial configuration value
//! let mut config = Config::load_from_file().await.unwrap();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! // Load initial configuration value
//! let mut config = Config::load_from_file().await.unwrap();
//!
//! // Create the watch channel, initialized with the loaded configuration
//! let (tx, rx) = watch::channel(config.clone());
//! // Create the watch channel, initialized with the loaded configuration
//! let (tx, rx) = watch::channel(config.clone());
//!
//! // Spawn a task to monitor the file.
//! tokio::spawn(async move {
//! loop {
//! // Wait 10 seconds between checks
//! time::sleep(Duration::from_secs(10)).await;
//!
//! // Load the configuration file
//! let new_config = Config::load_from_file().await.unwrap();
//!
//! // If the configuration changed, send the new config value
//! // on the watch channel.
//! if new_config != config {
//! tx.send(new_config.clone()).unwrap();
//! config = new_config;
//! }
//! }
//! });
//!
//! let mut handles = vec![];
//!
//! // Spawn tasks that runs the async operation for at most `timeout`. If
//! // the timeout elapses, restart the operation.
//! //
//! // The task simultaneously watches the `Config` for changes. When the
//! // timeout duration changes, the timeout is updated without restarting
//! // the in-flight operation.
//! for _ in 0..5 {
//! // Clone a config watch handle for use in this task
//! let mut rx = rx.clone();
//!
//! let handle = tokio::spawn(async move {
//! // Start the initial operation and pin the future to the stack.
//! // Pinning to the stack is required to resume the operation
//! // across multiple calls to `select!`
//! let op = my_async_operation();
//! tokio::pin!(op);
//!
//! // Get the initial config value
//! let mut conf = rx.borrow().clone();
//!
//! let mut op_start = Instant::now();
//! let sleep = time::sleep_until(op_start + conf.timeout);
//! tokio::pin!(sleep);
//!
//! // Spawn a task to monitor the file.
//! tokio::spawn(async move {
//! loop {
//! // Wait 10 seconds between checks
//! time::sleep(Duration::from_secs(10)).await;
//! tokio::select! {
//! _ = &mut sleep => {
//! // The operation elapsed. Restart it
//! op.set(my_async_operation());
//!
//! // Load the configuration file
//! let new_config = Config::load_from_file().await.unwrap();
//! // Track the new start time
//! op_start = Instant::now();
//!
//! // If the configuration changed, send the new config value
//! // on the watch channel.
//! if new_config != config {
//! tx.send(new_config.clone()).unwrap();
//! config = new_config;
//! // Restart the timeout
//! sleep.set(time::sleep_until(op_start + conf.timeout));
//! }
//! _ = rx.changed() => {
//! conf = rx.borrow_and_update().clone();
//!
//! // The configuration has been updated. Update the
//! // `sleep` using the new `timeout` value.
//! sleep.as_mut().reset(op_start + conf.timeout);
//! }
//! _ = &mut op => {
//! // The operation completed!
//! return
//! }
//! }
//! }
//! });
//!
//! let mut handles = vec![];
//!
//! // Spawn tasks that runs the async operation for at most `timeout`. If
//! // the timeout elapses, restart the operation.
//! //
//! // The task simultaneously watches the `Config` for changes. When the
//! // timeout duration changes, the timeout is updated without restarting
//! // the in-flight operation.
//! for _ in 0..5 {
//! // Clone a config watch handle for use in this task
//! let mut rx = rx.clone();
//!
//! let handle = tokio::spawn(async move {
//! // Start the initial operation and pin the future to the stack.
//! // Pinning to the stack is required to resume the operation
//! // across multiple calls to `select!`
//! let op = my_async_operation();
//! tokio::pin!(op);
//!
//! // Get the initial config value
//! let mut conf = rx.borrow().clone();
//!
//! let mut op_start = Instant::now();
//! let sleep = time::sleep_until(op_start + conf.timeout);
//! tokio::pin!(sleep);
//!
//! loop {
//! tokio::select! {
//! _ = &mut sleep => {
//! // The operation elapsed. Restart it
//! op.set(my_async_operation());
//!
//! // Track the new start time
//! op_start = Instant::now();
//!
//! // Restart the timeout
//! sleep.set(time::sleep_until(op_start + conf.timeout));
//! }
//! _ = rx.changed() => {
//! conf = rx.borrow_and_update().clone();
//!
//! // The configuration has been updated. Update the
//! // `sleep` using the new `timeout` value.
//! sleep.as_mut().reset(op_start + conf.timeout);
//! }
//! _ = &mut op => {
//! // The operation completed!
//! return
//! }
//! }
//! }
//! });
//!
//! handles.push(handle);
//! }
//!
//! for handle in handles.drain(..) {
//! handle.await.unwrap();
//! }
//! handles.push(handle);
//! }
//!
//! for handle in handles.drain(..) {
//! handle.await.unwrap();
//! }
//! # }
//! ```
//!
//! [`watch` channel]: mod@crate::sync::watch
File diff suppressed because it is too large Load Diff
+130 -124
View File
@@ -29,18 +29,18 @@ pub struct UnboundedSender<T> {
/// ```
/// use tokio::sync::mpsc::unbounded_channel;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx) = unbounded_channel::<i32>();
/// let tx_weak = tx.downgrade();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx) = unbounded_channel::<i32>();
/// let tx_weak = tx.downgrade();
///
/// // Upgrading will succeed because `tx` still exists.
/// assert!(tx_weak.upgrade().is_some());
/// // Upgrading will succeed because `tx` still exists.
/// assert!(tx_weak.upgrade().is_some());
///
/// // If we drop `tx`, then it will fail.
/// drop(tx);
/// assert!(tx_weak.clone().upgrade().is_none());
/// }
/// // If we drop `tx`, then it will fail.
/// drop(tx);
/// assert!(tx_weak.clone().upgrade().is_none());
/// # }
/// ```
pub struct WeakUnboundedSender<T> {
chan: Arc<chan::Chan<T, Semaphore>>,
@@ -135,17 +135,17 @@ impl<T> UnboundedReceiver<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = mpsc::unbounded_channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = mpsc::unbounded_channel();
///
/// tokio::spawn(async move {
/// tx.send("hello").unwrap();
/// });
/// tokio::spawn(async move {
/// tx.send("hello").unwrap();
/// });
///
/// assert_eq!(Some("hello"), rx.recv().await);
/// assert_eq!(None, rx.recv().await);
/// }
/// assert_eq!(Some("hello"), rx.recv().await);
/// assert_eq!(None, rx.recv().await);
/// # }
/// ```
///
/// Values are buffered:
@@ -153,16 +153,16 @@ impl<T> UnboundedReceiver<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = mpsc::unbounded_channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = mpsc::unbounded_channel();
///
/// tx.send("hello").unwrap();
/// tx.send("world").unwrap();
/// tx.send("hello").unwrap();
/// tx.send("world").unwrap();
///
/// assert_eq!(Some("hello"), rx.recv().await);
/// assert_eq!(Some("world"), rx.recv().await);
/// }
/// assert_eq!(Some("hello"), rx.recv().await);
/// assert_eq!(Some("world"), rx.recv().await);
/// # }
/// ```
pub async fn recv(&mut self) -> Option<T> {
use std::future::poll_fn;
@@ -203,40 +203,40 @@ impl<T> UnboundedReceiver<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let mut buffer: Vec<&str> = Vec::with_capacity(2);
/// let limit = 2;
/// let (tx, mut rx) = mpsc::unbounded_channel();
/// let tx2 = tx.clone();
/// tx2.send("first").unwrap();
/// tx2.send("second").unwrap();
/// tx2.send("third").unwrap();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut buffer: Vec<&str> = Vec::with_capacity(2);
/// let limit = 2;
/// let (tx, mut rx) = mpsc::unbounded_channel();
/// let tx2 = tx.clone();
/// tx2.send("first").unwrap();
/// tx2.send("second").unwrap();
/// tx2.send("third").unwrap();
///
/// // Call `recv_many` to receive up to `limit` (2) values.
/// assert_eq!(2, rx.recv_many(&mut buffer, limit).await);
/// assert_eq!(vec!["first", "second"], buffer);
/// // Call `recv_many` to receive up to `limit` (2) values.
/// assert_eq!(2, rx.recv_many(&mut buffer, limit).await);
/// assert_eq!(vec!["first", "second"], buffer);
///
/// // If the buffer is full, the next call to `recv_many`
/// // reserves additional capacity.
/// assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
/// // If the buffer is full, the next call to `recv_many`
/// // reserves additional capacity.
/// assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
///
/// tokio::spawn(async move {
/// tx.send("fourth").unwrap();
/// });
/// tokio::spawn(async move {
/// tx.send("fourth").unwrap();
/// });
///
/// // 'tx' is dropped, but `recv_many`
/// // is guaranteed not to return 0 as the channel
/// // is not yet closed.
/// assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
/// assert_eq!(vec!["first", "second", "third", "fourth"], buffer);
/// // 'tx' is dropped, but `recv_many`
/// // is guaranteed not to return 0 as the channel
/// // is not yet closed.
/// assert_eq!(1, rx.recv_many(&mut buffer, limit).await);
/// assert_eq!(vec!["first", "second", "third", "fourth"], buffer);
///
/// // Once the last sender is dropped, the channel is
/// // closed and `recv_many` returns 0, capacity unchanged.
/// drop(tx2);
/// assert_eq!(0, rx.recv_many(&mut buffer, limit).await);
/// assert_eq!(vec!["first", "second", "third", "fourth"], buffer);
/// }
/// // Once the last sender is dropped, the channel is
/// // closed and `recv_many` returns 0, capacity unchanged.
/// drop(tx2);
/// assert_eq!(0, rx.recv_many(&mut buffer, limit).await);
/// assert_eq!(vec!["first", "second", "third", "fourth"], buffer);
/// # }
/// ```
pub async fn recv_many(&mut self, buffer: &mut Vec<T>, limit: usize) -> usize {
use std::future::poll_fn;
@@ -266,22 +266,22 @@ impl<T> UnboundedReceiver<T> {
/// use tokio::sync::mpsc;
/// use tokio::sync::mpsc::error::TryRecvError;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = mpsc::unbounded_channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = mpsc::unbounded_channel();
///
/// tx.send("hello").unwrap();
/// tx.send("hello").unwrap();
///
/// assert_eq!(Ok("hello"), rx.try_recv());
/// assert_eq!(Err(TryRecvError::Empty), rx.try_recv());
/// assert_eq!(Ok("hello"), rx.try_recv());
/// assert_eq!(Err(TryRecvError::Empty), rx.try_recv());
///
/// tx.send("hello").unwrap();
/// // Drop the last sender, closing the channel.
/// drop(tx);
/// tx.send("hello").unwrap();
/// // Drop the last sender, closing the channel.
/// drop(tx);
///
/// assert_eq!(Ok("hello"), rx.try_recv());
/// assert_eq!(Err(TryRecvError::Disconnected), rx.try_recv());
/// }
/// assert_eq!(Ok("hello"), rx.try_recv());
/// assert_eq!(Err(TryRecvError::Disconnected), rx.try_recv());
/// # }
/// ```
pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
self.chan.try_recv()
@@ -297,6 +297,8 @@ impl<T> UnboundedReceiver<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::thread;
/// use tokio::sync::mpsc;
///
@@ -311,6 +313,7 @@ impl<T> UnboundedReceiver<T> {
/// let _ = tx.send(10);
/// sync_code.join().unwrap();
/// }
/// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
@@ -352,15 +355,15 @@ impl<T> UnboundedReceiver<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let (_tx, mut rx) = mpsc::unbounded_channel::<()>();
/// assert!(!rx.is_closed());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (_tx, mut rx) = mpsc::unbounded_channel::<()>();
/// assert!(!rx.is_closed());
///
/// rx.close();
/// rx.close();
///
/// assert!(rx.is_closed());
/// }
/// assert!(rx.is_closed());
/// # }
/// ```
pub fn is_closed(&self) -> bool {
self.chan.is_closed()
@@ -374,14 +377,14 @@ impl<T> UnboundedReceiver<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = mpsc::unbounded_channel();
/// assert!(rx.is_empty());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = mpsc::unbounded_channel();
/// assert!(rx.is_empty());
///
/// tx.send(0).unwrap();
/// assert!(!rx.is_empty());
/// }
/// tx.send(0).unwrap();
/// assert!(!rx.is_empty());
/// # }
///
/// ```
pub fn is_empty(&self) -> bool {
@@ -394,14 +397,14 @@ impl<T> UnboundedReceiver<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = mpsc::unbounded_channel();
/// assert_eq!(0, rx.len());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = mpsc::unbounded_channel();
/// assert_eq!(0, rx.len());
///
/// tx.send(0).unwrap();
/// assert_eq!(1, rx.len());
/// }
/// tx.send(0).unwrap();
/// assert_eq!(1, rx.len());
/// # }
/// ```
pub fn len(&self) -> usize {
self.chan.len()
@@ -455,6 +458,8 @@ impl<T> UnboundedReceiver<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::task::{Context, Poll};
/// use std::pin::Pin;
/// use tokio::sync::mpsc;
@@ -480,25 +485,26 @@ impl<T> UnboundedReceiver<T> {
/// }
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = mpsc::unbounded_channel::<i32>();
/// let mut buffer = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = mpsc::unbounded_channel::<i32>();
/// let mut buffer = Vec::new();
///
/// let my_receiver_future = MyReceiverFuture {
/// receiver: rx,
/// buffer: &mut buffer,
/// limit: 3,
/// };
/// let my_receiver_future = MyReceiverFuture {
/// receiver: rx,
/// buffer: &mut buffer,
/// limit: 3,
/// };
///
/// for i in 0..10 {
/// tx.send(i).expect("Unable to send integer");
/// }
///
/// let count = my_receiver_future.await;
/// assert_eq!(count, 3);
/// assert_eq!(buffer, vec![0,1,2])
/// for i in 0..10 {
/// tx.send(i).expect("Unable to send integer");
/// }
///
/// let count = my_receiver_future.await;
/// assert_eq!(count, 3);
/// assert_eq!(buffer, vec![0,1,2])
/// # }
/// # }
/// ```
pub fn poll_recv_many(
&mut self,
@@ -592,26 +598,26 @@ impl<T> UnboundedSender<T> {
/// ```
/// use tokio::sync::mpsc;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx1, rx) = mpsc::unbounded_channel::<()>();
/// let tx2 = tx1.clone();
/// let tx3 = tx1.clone();
/// let tx4 = tx1.clone();
/// let tx5 = tx1.clone();
/// tokio::spawn(async move {
/// drop(rx);
/// });
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx1, rx) = mpsc::unbounded_channel::<()>();
/// let tx2 = tx1.clone();
/// let tx3 = tx1.clone();
/// let tx4 = tx1.clone();
/// let tx5 = tx1.clone();
/// tokio::spawn(async move {
/// drop(rx);
/// });
///
/// futures::join!(
/// tx1.closed(),
/// tx2.closed(),
/// tx3.closed(),
/// tx4.closed(),
/// tx5.closed()
/// );
//// println!("Receiver dropped");
/// }
/// futures::join!(
/// tx1.closed(),
/// tx2.closed(),
/// tx3.closed(),
/// tx4.closed(),
/// tx5.closed()
/// );
/// println!("Receiver dropped");
/// # }
/// ```
pub async fn closed(&self) {
self.chan.closed().await;
+60 -56
View File
@@ -59,19 +59,19 @@ use std::{fmt, mem, ptr};
/// use tokio::sync::Mutex;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let data1 = Arc::new(Mutex::new(0));
/// let data2 = Arc::clone(&data1);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let data1 = Arc::new(Mutex::new(0));
/// let data2 = Arc::clone(&data1);
///
/// tokio::spawn(async move {
/// let mut lock = data2.lock().await;
/// *lock += 1;
/// });
///
/// let mut lock = data1.lock().await;
/// tokio::spawn(async move {
/// let mut lock = data2.lock().await;
/// *lock += 1;
/// }
/// });
///
/// let mut lock = data1.lock().await;
/// *lock += 1;
/// # }
/// ```
///
///
@@ -79,28 +79,28 @@ use std::{fmt, mem, ptr};
/// use tokio::sync::Mutex;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let count = Arc::new(Mutex::new(0));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let count = Arc::new(Mutex::new(0));
///
/// for i in 0..5 {
/// let my_count = Arc::clone(&count);
/// tokio::spawn(async move {
/// for j in 0..10 {
/// let mut lock = my_count.lock().await;
/// *lock += 1;
/// println!("{} {} {}", i, j, lock);
/// }
/// });
/// }
///
/// loop {
/// if *count.lock().await >= 50 {
/// break;
/// for i in 0..5 {
/// let my_count = Arc::clone(&count);
/// tokio::spawn(async move {
/// for j in 0..10 {
/// let mut lock = my_count.lock().await;
/// *lock += 1;
/// println!("{} {} {}", i, j, lock);
/// }
/// }
/// println!("Count hit 50.");
/// });
/// }
///
/// loop {
/// if *count.lock().await >= 50 {
/// break;
/// }
/// }
/// println!("Count hit 50.");
/// # }
/// ```
/// There are a few things of note here to pay attention to in this example.
/// 1. The mutex is wrapped in an [`Arc`] to allow it to be shared across
@@ -423,13 +423,13 @@ impl<T: ?Sized> Mutex<T> {
/// ```
/// use tokio::sync::Mutex;
///
/// #[tokio::main]
/// async fn main() {
/// let mutex = Mutex::new(1);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mutex = Mutex::new(1);
///
/// let mut n = mutex.lock().await;
/// *n = 2;
/// }
/// let mut n = mutex.lock().await;
/// *n = 2;
/// # }
/// ```
pub async fn lock(&self) -> MutexGuard<'_, T> {
let acquire_fut = async {
@@ -484,6 +484,8 @@ impl<T: ?Sized> Mutex<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::Arc;
/// use tokio::sync::Mutex;
///
@@ -510,7 +512,7 @@ impl<T: ?Sized> Mutex<T> {
/// let n = mutex.try_lock().unwrap();
/// assert_eq!(*n, 2);
/// }
///
/// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
@@ -541,6 +543,8 @@ impl<T: ?Sized> Mutex<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::Arc;
/// use tokio::sync::Mutex;
///
@@ -567,7 +571,7 @@ impl<T: ?Sized> Mutex<T> {
/// let n = mutex.try_lock().unwrap();
/// assert_eq!(*n, 2);
/// }
///
/// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
@@ -601,13 +605,13 @@ impl<T: ?Sized> Mutex<T> {
/// use tokio::sync::Mutex;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let mutex = Arc::new(Mutex::new(1));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mutex = Arc::new(Mutex::new(1));
///
/// let mut n = mutex.clone().lock_owned().await;
/// *n = 2;
/// }
/// let mut n = mutex.clone().lock_owned().await;
/// *n = 2;
/// # }
/// ```
///
/// [`Arc`]: std::sync::Arc
@@ -772,13 +776,13 @@ impl<T: ?Sized> Mutex<T> {
/// ```
/// use tokio::sync::Mutex;
///
/// #[tokio::main]
/// async fn main() {
/// let mutex = Mutex::new(1);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mutex = Mutex::new(1);
///
/// let n = mutex.into_inner();
/// assert_eq!(n, 1);
/// }
/// let n = mutex.into_inner();
/// assert_eq!(n, 1);
/// # }
/// ```
pub fn into_inner(self) -> T
where
@@ -846,7 +850,7 @@ impl<'a, T: ?Sized> MutexGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let foo = Mutex::new(Foo(1));
///
@@ -894,7 +898,7 @@ impl<'a, T: ?Sized> MutexGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let foo = Mutex::new(Foo(1));
///
@@ -944,7 +948,7 @@ impl<'a, T: ?Sized> MutexGuard<'a, T> {
/// guard
/// }
/// #
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// # let mutex = Mutex::new(0u32);
/// # let guard = mutex.lock().await;
@@ -1028,7 +1032,7 @@ impl<T: ?Sized> OwnedMutexGuard<T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let foo = Arc::new(Mutex::new(Foo(1)));
///
@@ -1076,7 +1080,7 @@ impl<T: ?Sized> OwnedMutexGuard<T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let foo = Arc::new(Mutex::new(Foo(1)));
///
@@ -1126,7 +1130,7 @@ impl<T: ?Sized> OwnedMutexGuard<T> {
/// guard
/// }
/// #
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// # let mutex = Arc::new(Mutex::new(0u32));
/// # let guard = mutex.lock_owned().await;
+62 -62
View File
@@ -56,22 +56,22 @@ type GuardedWaitList = GuardedLinkedList<Waiter, <Waiter as linked_list::Link>::
/// use tokio::sync::Notify;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
///
/// let handle = tokio::spawn(async move {
/// notify2.notified().await;
/// println!("received notification");
/// });
/// let handle = tokio::spawn(async move {
/// notify2.notified().await;
/// println!("received notification");
/// });
///
/// println!("sending notification");
/// notify.notify_one();
/// println!("sending notification");
/// notify.notify_one();
///
/// // Wait for task to receive notification.
/// handle.await.unwrap();
/// }
/// // Wait for task to receive notification.
/// handle.await.unwrap();
/// # }
/// ```
///
/// Unbound multi-producer single-consumer (mpsc) channel.
@@ -548,19 +548,19 @@ impl Notify {
/// use tokio::sync::Notify;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
///
/// tokio::spawn(async move {
/// notify2.notified().await;
/// println!("received notification");
/// });
/// tokio::spawn(async move {
/// notify2.notified().await;
/// println!("received notification");
/// });
///
/// println!("sending notification");
/// notify.notify_one();
/// }
/// println!("sending notification");
/// notify.notify_one();
/// # }
/// ```
pub fn notified(&self) -> Notified<'_> {
// we load the number of times notify_waiters
@@ -594,21 +594,21 @@ impl Notify {
/// use std::sync::Arc;
/// use tokio::sync::Notify;
///
/// #[tokio::main]
/// async fn main() {
/// let notify = Arc::new(Notify::new());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let notify = Arc::new(Notify::new());
///
/// for _ in 0..10 {
/// let notified = notify.clone().notified_owned();
/// tokio::spawn(async move {
/// notified.await;
/// println!("received notification");
/// });
/// }
///
/// println!("sending notification");
/// notify.notify_waiters();
/// for _ in 0..10 {
/// let notified = notify.clone().notified_owned();
/// tokio::spawn(async move {
/// notified.await;
/// println!("received notification");
/// });
/// }
///
/// println!("sending notification");
/// notify.notify_waiters();
/// # }
/// ```
pub fn notified_owned(self: Arc<Self>) -> OwnedNotified {
// we load the number of times notify_waiters
@@ -641,19 +641,19 @@ impl Notify {
/// use tokio::sync::Notify;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
///
/// tokio::spawn(async move {
/// notify2.notified().await;
/// println!("received notification");
/// });
/// tokio::spawn(async move {
/// notify2.notified().await;
/// println!("received notification");
/// });
///
/// println!("sending notification");
/// notify.notify_one();
/// }
/// println!("sending notification");
/// notify.notify_one();
/// # }
/// ```
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "notify"))]
@@ -722,23 +722,23 @@ impl Notify {
/// use tokio::sync::Notify;
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let notify = Arc::new(Notify::new());
/// let notify2 = notify.clone();
///
/// let notified1 = notify.notified();
/// let notified2 = notify.notified();
/// let notified1 = notify.notified();
/// let notified2 = notify.notified();
///
/// let handle = tokio::spawn(async move {
/// println!("sending notifications");
/// notify2.notify_waiters();
/// });
/// let handle = tokio::spawn(async move {
/// println!("sending notifications");
/// notify2.notify_waiters();
/// });
///
/// notified1.await;
/// notified2.await;
/// println!("received notifications");
/// }
/// notified1.await;
/// notified2.await;
/// println!("received notifications");
/// # }
/// ```
pub fn notify_waiters(&self) {
self.lock_waiter_list().notify_waiters();
+20 -20
View File
@@ -41,11 +41,11 @@ use std::sync::atomic::{AtomicBool, Ordering};
///
/// static ONCE: OnceCell<u32> = OnceCell::const_new();
///
/// #[tokio::main]
/// async fn main() {
/// let result = ONCE.get_or_init(some_computation).await;
/// assert_eq!(*result, 2);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let result = ONCE.get_or_init(some_computation).await;
/// assert_eq!(*result, 2);
/// # }
/// ```
///
/// It is often useful to write a wrapper method for accessing the value.
@@ -61,11 +61,11 @@ use std::sync::atomic::{AtomicBool, Ordering};
/// }).await
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let result = get_global_integer().await;
/// assert_eq!(*result, 2);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let result = get_global_integer().await;
/// assert_eq!(*result, 2);
/// # }
/// ```
pub struct OnceCell<T> {
value_set: AtomicBool,
@@ -155,11 +155,11 @@ impl<T> OnceCell<T> {
/// }).await
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let result = get_global_integer().await;
/// assert_eq!(*result, 2);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let result = get_global_integer().await;
/// assert_eq!(*result, 2);
/// # }
/// ```
///
/// [`tokio-console`]: https://github.com/tokio-rs/console
@@ -210,11 +210,11 @@ impl<T> OnceCell<T> {
/// }).await
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let result = get_global_integer().await;
/// assert_eq!(*result, 1);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let result = get_global_integer().await;
/// assert_eq!(*result, 1);
/// # }
/// ```
///
/// [`tokio-console`]: https://github.com/tokio-rs/console
+274 -271
View File
@@ -21,21 +21,21 @@
//! ```
//! use tokio::sync::oneshot;
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, rx) = oneshot::channel();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, rx) = oneshot::channel();
//!
//! tokio::spawn(async move {
//! if let Err(_) = tx.send(3) {
//! println!("the receiver dropped");
//! }
//! });
//!
//! match rx.await {
//! Ok(v) => println!("got = {:?}", v),
//! Err(_) => println!("the sender dropped"),
//! tokio::spawn(async move {
//! if let Err(_) = tx.send(3) {
//! println!("the receiver dropped");
//! }
//! });
//!
//! match rx.await {
//! Ok(v) => println!("got = {:?}", v),
//! Err(_) => println!("the sender dropped"),
//! }
//! # }
//! ```
//!
//! If the sender is dropped without sending, the receiver will fail with
@@ -44,19 +44,19 @@
//! ```
//! use tokio::sync::oneshot;
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, rx) = oneshot::channel::<u32>();
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, rx) = oneshot::channel::<u32>();
//!
//! tokio::spawn(async move {
//! drop(tx);
//! });
//! tokio::spawn(async move {
//! drop(tx);
//! });
//!
//! match rx.await {
//! Ok(_) => panic!("This doesn't happen"),
//! Err(_) => println!("the sender dropped"),
//! }
//! match rx.await {
//! Ok(_) => panic!("This doesn't happen"),
//! Err(_) => println!("the sender dropped"),
//! }
//! # }
//! ```
//!
//! To use a `oneshot` channel in a `tokio::select!` loop, add `&mut` in front of
@@ -66,30 +66,30 @@
//! use tokio::sync::oneshot;
//! use tokio::time::{interval, sleep, Duration};
//!
//! #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn _doc() {}
//! # #[tokio::main(flavor = "current_thread", start_paused = true)]
//! async fn main() {
//! let (send, mut recv) = oneshot::channel();
//! let mut interval = interval(Duration::from_millis(100));
//! # async fn main() {
//! let (send, mut recv) = oneshot::channel();
//! let mut interval = interval(Duration::from_millis(100));
//!
//! # let handle =
//! tokio::spawn(async move {
//! sleep(Duration::from_secs(1)).await;
//! send.send("shut down").unwrap();
//! });
//! # let handle =
//! tokio::spawn(async move {
//! sleep(Duration::from_secs(1)).await;
//! send.send("shut down").unwrap();
//! });
//!
//! loop {
//! tokio::select! {
//! _ = interval.tick() => println!("Another 100ms"),
//! msg = &mut recv => {
//! println!("Got message: {}", msg.unwrap());
//! break;
//! }
//! loop {
//! tokio::select! {
//! _ = interval.tick() => println!("Another 100ms"),
//! msg = &mut recv => {
//! println!("Got message: {}", msg.unwrap());
//! break;
//! }
//! }
//! # handle.await.unwrap();
//! }
//! # handle.await.unwrap();
//! # }
//! ```
//!
//! To use a `Sender` from a destructor, put it in an [`Option`] and call
@@ -110,17 +110,17 @@
//! }
//! }
//!
//! #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn _doc() {}
//! # #[tokio::main(flavor = "current_thread")]
//! async fn main() {
//! let (send, recv) = oneshot::channel();
//! # async fn main() {
//! let (send, recv) = oneshot::channel();
//!
//! let send_on_drop = SendOnDrop { sender: Some(send) };
//! drop(send_on_drop);
//! let send_on_drop = SendOnDrop { sender: Some(send) };
//! drop(send_on_drop);
//!
//! assert_eq!(recv.await, Ok("I got dropped!"));
//! }
//! assert_eq!(recv.await, Ok("I got dropped!"));
//! # }
//! ```
use crate::loom::cell::UnsafeCell;
@@ -147,21 +147,21 @@ use std::task::{ready, Context, Poll, Waker};
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel();
///
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// }
/// # }
/// ```
///
/// If the sender is dropped without sending, the receiver will fail with
@@ -170,19 +170,19 @@ use std::task::{ready, Context, Poll, Waker};
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel::<u32>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel::<u32>();
///
/// tokio::spawn(async move {
/// drop(tx);
/// });
/// tokio::spawn(async move {
/// drop(tx);
/// });
///
/// match rx.await {
/// Ok(_) => panic!("This doesn't happen"),
/// Err(_) => println!("the sender dropped"),
/// }
/// match rx.await {
/// Ok(_) => panic!("This doesn't happen"),
/// Err(_) => println!("the sender dropped"),
/// }
/// # }
/// ```
///
/// To use a `Sender` from a destructor, put it in an [`Option`] and call
@@ -203,17 +203,17 @@ use std::task::{ready, Context, Poll, Waker};
/// }
/// }
///
/// #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn _doc() {}
/// # #[tokio::main(flavor = "current_thread")]
/// async fn main() {
/// let (send, recv) = oneshot::channel();
/// # async fn main() {
/// let (send, recv) = oneshot::channel();
///
/// let send_on_drop = SendOnDrop { sender: Some(send) };
/// drop(send_on_drop);
/// let send_on_drop = SendOnDrop { sender: Some(send) };
/// drop(send_on_drop);
///
/// assert_eq!(recv.await, Ok("I got dropped!"));
/// }
/// assert_eq!(recv.await, Ok("I got dropped!"));
/// # }
/// ```
///
/// [`Option`]: std::option::Option
@@ -248,21 +248,21 @@ pub struct Sender<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel();
///
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// }
/// # }
/// ```
///
/// If the sender is dropped without sending, the receiver will fail with
@@ -271,19 +271,19 @@ pub struct Sender<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel::<u32>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel::<u32>();
///
/// tokio::spawn(async move {
/// drop(tx);
/// });
/// tokio::spawn(async move {
/// drop(tx);
/// });
///
/// match rx.await {
/// Ok(_) => panic!("This doesn't happen"),
/// Err(_) => println!("the sender dropped"),
/// }
/// match rx.await {
/// Ok(_) => panic!("This doesn't happen"),
/// Err(_) => println!("the sender dropped"),
/// }
/// # }
/// ```
///
/// To use a `Receiver` in a `tokio::select!` loop, add `&mut` in front of the
@@ -293,30 +293,30 @@ pub struct Sender<T> {
/// use tokio::sync::oneshot;
/// use tokio::time::{interval, sleep, Duration};
///
/// #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn _doc() {}
/// # #[tokio::main(flavor = "current_thread", start_paused = true)]
/// async fn main() {
/// let (send, mut recv) = oneshot::channel();
/// let mut interval = interval(Duration::from_millis(100));
/// # async fn main() {
/// let (send, mut recv) = oneshot::channel();
/// let mut interval = interval(Duration::from_millis(100));
///
/// # let handle =
/// tokio::spawn(async move {
/// sleep(Duration::from_secs(1)).await;
/// send.send("shut down").unwrap();
/// });
/// # let handle =
/// tokio::spawn(async move {
/// sleep(Duration::from_secs(1)).await;
/// send.send("shut down").unwrap();
/// });
///
/// loop {
/// tokio::select! {
/// _ = interval.tick() => println!("Another 100ms"),
/// msg = &mut recv => {
/// println!("Got message: {}", msg.unwrap());
/// break;
/// }
/// loop {
/// tokio::select! {
/// _ = interval.tick() => println!("Another 100ms"),
/// msg = &mut recv => {
/// println!("Got message: {}", msg.unwrap());
/// break;
/// }
/// }
/// # handle.await.unwrap();
/// }
/// # handle.await.unwrap();
/// # }
/// ```
#[derive(Debug)]
pub struct Receiver<T> {
@@ -450,21 +450,21 @@ struct State(usize);
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel();
///
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// }
/// # }
/// ```
#[track_caller]
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
@@ -576,21 +576,21 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel();
///
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// tokio::spawn(async move {
/// if let Err(_) = tx.send(3) {
/// println!("the receiver dropped");
/// }
/// });
///
/// match rx.await {
/// Ok(v) => println!("got = {:?}", v),
/// Err(_) => println!("the sender dropped"),
/// }
/// # }
/// ```
pub fn send(mut self, t: T) -> Result<(), T> {
let inner = self.inner.take().unwrap();
@@ -652,17 +652,17 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (mut tx, rx) = oneshot::channel::<()>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (mut tx, rx) = oneshot::channel::<()>();
///
/// tokio::spawn(async move {
/// drop(rx);
/// });
/// tokio::spawn(async move {
/// drop(rx);
/// });
///
/// tx.closed().await;
/// println!("the receiver dropped");
/// }
/// tx.closed().await;
/// println!("the receiver dropped");
/// # }
/// ```
///
/// Paired with select
@@ -676,26 +676,26 @@ impl<T> Sender<T> {
/// # "hello".to_string()
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let (mut tx, rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (mut tx, rx) = oneshot::channel();
///
/// tokio::spawn(async move {
/// tokio::select! {
/// _ = tx.closed() => {
/// // The receiver dropped, no need to do any further work
/// }
/// value = compute() => {
/// // The send can fail if the channel was closed at the exact same
/// // time as when compute() finished, so just ignore the failure.
/// let _ = tx.send(value);
/// }
/// tokio::spawn(async move {
/// tokio::select! {
/// _ = tx.closed() => {
/// // The receiver dropped, no need to do any further work
/// }
/// });
/// value = compute() => {
/// // The send can fail if the channel was closed at the exact same
/// // time as when compute() finished, so just ignore the failure.
/// let _ = tx.send(value);
/// }
/// }
/// });
///
/// // Wait for up to 10 seconds
/// let _ = time::timeout(Duration::from_secs(10), rx).await;
/// }
/// // Wait for up to 10 seconds
/// let _ = time::timeout(Duration::from_secs(10), rx).await;
/// # }
/// ```
pub async fn closed(&mut self) {
use std::future::poll_fn;
@@ -731,17 +731,17 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = oneshot::channel();
///
/// assert!(!tx.is_closed());
/// assert!(!tx.is_closed());
///
/// drop(rx);
/// drop(rx);
///
/// assert!(tx.is_closed());
/// assert!(tx.send("never received").is_err());
/// }
/// assert!(tx.is_closed());
/// assert!(tx.send("never received").is_err());
/// # }
/// ```
pub fn is_closed(&self) -> bool {
let inner = self.inner.as_ref().unwrap();
@@ -777,18 +777,18 @@ impl<T> Sender<T> {
///
/// use std::future::poll_fn;
///
/// #[tokio::main]
/// async fn main() {
/// let (mut tx, mut rx) = oneshot::channel::<()>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (mut tx, mut rx) = oneshot::channel::<()>();
///
/// tokio::spawn(async move {
/// rx.close();
/// });
/// tokio::spawn(async move {
/// rx.close();
/// });
///
/// poll_fn(|cx| tx.poll_closed(cx)).await;
/// poll_fn(|cx| tx.poll_closed(cx)).await;
///
/// println!("the receiver dropped");
/// }
/// println!("the receiver dropped");
/// # }
/// ```
pub fn poll_closed(&mut self, cx: &mut Context<'_>) -> Poll<()> {
ready!(crate::trace::trace_leaf(cx));
@@ -882,22 +882,22 @@ impl<T> Receiver<T> {
/// use tokio::sync::oneshot;
/// use tokio::sync::oneshot::error::TryRecvError;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel();
///
/// assert!(!tx.is_closed());
/// assert!(!tx.is_closed());
///
/// rx.close();
/// rx.close();
///
/// assert!(tx.is_closed());
/// assert!(tx.send("never received").is_err());
/// assert!(tx.is_closed());
/// assert!(tx.send("never received").is_err());
///
/// match rx.try_recv() {
/// Err(TryRecvError::Closed) => {}
/// _ => unreachable!(),
/// }
/// match rx.try_recv() {
/// Err(TryRecvError::Closed) => {}
/// _ => unreachable!(),
/// }
/// # }
/// ```
///
/// Receive a value sent **before** calling `close`
@@ -905,17 +905,17 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel();
///
/// assert!(tx.send("will receive").is_ok());
/// assert!(tx.send("will receive").is_ok());
///
/// rx.close();
/// rx.close();
///
/// let msg = rx.try_recv().unwrap();
/// assert_eq!(msg, "will receive");
/// }
/// let msg = rx.try_recv().unwrap();
/// assert_eq!(msg, "will receive");
/// # }
/// ```
pub fn close(&mut self) {
if let Some(inner) = self.inner.as_ref() {
@@ -945,26 +945,26 @@ impl<T> Receiver<T> {
///
/// use std::task::Poll;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel();
///
/// // A receiver is not terminated when it is initialized.
/// assert!(!rx.is_terminated());
/// // A receiver is not terminated when it is initialized.
/// assert!(!rx.is_terminated());
///
/// // A receiver is not terminated it is polled and is still pending.
/// let poll = futures::poll!(&mut rx);
/// assert_eq!(poll, Poll::Pending);
/// assert!(!rx.is_terminated());
/// // A receiver is not terminated it is polled and is still pending.
/// let poll = futures::poll!(&mut rx);
/// assert_eq!(poll, Poll::Pending);
/// assert!(!rx.is_terminated());
///
/// // A receiver is not terminated if a value has been sent, but not yet read.
/// tx.send(0).unwrap();
/// assert!(!rx.is_terminated());
/// // A receiver is not terminated if a value has been sent, but not yet read.
/// tx.send(0).unwrap();
/// assert!(!rx.is_terminated());
///
/// // A receiver *is* terminated after it has been polled and yielded a value.
/// assert_eq!((&mut rx).await, Ok(0));
/// assert!(rx.is_terminated());
/// }
/// // A receiver *is* terminated after it has been polled and yielded a value.
/// assert_eq!((&mut rx).await, Ok(0));
/// assert!(rx.is_terminated());
/// # }
/// ```
///
/// Dropping the sender.
@@ -972,18 +972,18 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel::<()>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel::<()>();
///
/// // A receiver is not immediately terminated when the sender is dropped.
/// drop(tx);
/// assert!(!rx.is_terminated());
/// // A receiver is not immediately terminated when the sender is dropped.
/// drop(tx);
/// assert!(!rx.is_terminated());
///
/// // A receiver *is* terminated after it has been polled and yielded an error.
/// let _ = (&mut rx).await.unwrap_err();
/// assert!(rx.is_terminated());
/// }
/// // A receiver *is* terminated after it has been polled and yielded an error.
/// let _ = (&mut rx).await.unwrap_err();
/// assert!(rx.is_terminated());
/// # }
/// ```
pub fn is_terminated(&self) -> bool {
self.inner.is_none()
@@ -1004,17 +1004,17 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel();
/// assert!(rx.is_empty());
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel();
/// assert!(rx.is_empty());
///
/// tx.send(0).unwrap();
/// assert!(!rx.is_empty());
/// tx.send(0).unwrap();
/// assert!(!rx.is_empty());
///
/// let _ = (&mut rx).await;
/// assert!(rx.is_empty());
/// }
/// let _ = (&mut rx).await;
/// assert!(rx.is_empty());
/// # }
/// ```
///
/// Dropping the sender.
@@ -1022,23 +1022,23 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel::<()>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel::<()>();
///
/// // A channel is empty if the sender is dropped.
/// drop(tx);
/// assert!(rx.is_empty());
/// // A channel is empty if the sender is dropped.
/// drop(tx);
/// assert!(rx.is_empty());
///
/// // A closed channel still yields an error, however.
/// (&mut rx).await.expect_err("should yield an error");
/// assert!(rx.is_empty());
/// }
/// // A closed channel still yields an error, however.
/// (&mut rx).await.expect_err("should yield an error");
/// assert!(rx.is_empty());
/// # }
/// ```
///
/// Terminated channels are empty.
///
/// ```should_panic
/// ```should_panic,ignore-wasm
/// use tokio::sync::oneshot;
///
/// #[tokio::main]
@@ -1102,24 +1102,24 @@ impl<T> Receiver<T> {
/// use tokio::sync::oneshot;
/// use tokio::sync::oneshot::error::TryRecvError;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel();
///
/// match rx.try_recv() {
/// // The channel is currently empty
/// Err(TryRecvError::Empty) => {}
/// _ => unreachable!(),
/// }
///
/// // Send a value
/// tx.send("hello").unwrap();
///
/// match rx.try_recv() {
/// Ok(value) => assert_eq!(value, "hello"),
/// _ => unreachable!(),
/// }
/// match rx.try_recv() {
/// // The channel is currently empty
/// Err(TryRecvError::Empty) => {}
/// _ => unreachable!(),
/// }
///
/// // Send a value
/// tx.send("hello").unwrap();
///
/// match rx.try_recv() {
/// Ok(value) => assert_eq!(value, "hello"),
/// _ => unreachable!(),
/// }
/// # }
/// ```
///
/// `try_recv` when the sender dropped before sending a value
@@ -1128,18 +1128,18 @@ impl<T> Receiver<T> {
/// use tokio::sync::oneshot;
/// use tokio::sync::oneshot::error::TryRecvError;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = oneshot::channel::<()>();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = oneshot::channel::<()>();
///
/// drop(tx);
/// drop(tx);
///
/// match rx.try_recv() {
/// // The channel will never receive a value.
/// Err(TryRecvError::Closed) => {}
/// _ => unreachable!(),
/// }
/// match rx.try_recv() {
/// // The channel will never receive a value.
/// Err(TryRecvError::Closed) => {}
/// _ => unreachable!(),
/// }
/// # }
/// ```
pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
let result = if let Some(inner) = self.inner.as_ref() {
@@ -1189,6 +1189,8 @@ impl<T> Receiver<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::thread;
/// use tokio::sync::oneshot;
///
@@ -1203,6 +1205,7 @@ impl<T> Receiver<T> {
/// let _ = tx.send(10);
/// sync_code.join().unwrap();
/// }
/// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
+103 -97
View File
@@ -58,25 +58,25 @@ const MAX_READS: u32 = 10;
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = RwLock::new(5);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(5);
///
/// // many reader locks can be held at once
/// {
/// let r1 = lock.read().await;
/// let r2 = lock.read().await;
/// assert_eq!(*r1, 5);
/// assert_eq!(*r2, 5);
/// } // read locks are dropped at this point
/// // many reader locks can be held at once
/// {
/// let r1 = lock.read().await;
/// let r2 = lock.read().await;
/// assert_eq!(*r1, 5);
/// assert_eq!(*r2, 5);
/// } // read locks are dropped at this point
///
/// // only one write lock may be held, however
/// {
/// let mut w = lock.write().await;
/// *w += 1;
/// assert_eq!(*w, 6);
/// } // write lock is dropped here
/// }
/// // only one write lock may be held, however
/// {
/// let mut w = lock.write().await;
/// *w += 1;
/// assert_eq!(*w, 6);
/// } // write lock is dropped here
/// # }
/// ```
///
/// [`Mutex`]: struct@super::Mutex
@@ -410,23 +410,23 @@ impl<T: ?Sized> RwLock<T> {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let n = lock.read().await;
/// assert_eq!(*n, 1);
/// let n = lock.read().await;
/// assert_eq!(*n, 1);
///
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let r = c_lock.read().await;
/// assert_eq!(*r, 1);
/// }).await.expect("The spawned task has panicked");
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let r = c_lock.read().await;
/// assert_eq!(*r, 1);
/// }).await.expect("The spawned task has panicked");
///
/// // Drop the guard after the spawned task finishes.
/// drop(n);
/// }
/// // Drop the guard after the spawned task finishes.
/// drop(n);
/// # }
/// ```
pub async fn read(&self) -> RwLockReadGuard<'_, T> {
let acquire_fut = async {
@@ -489,6 +489,8 @@ impl<T: ?Sized> RwLock<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
@@ -515,6 +517,7 @@ impl<T: ?Sized> RwLock<T> {
/// // Assert uncontended.
/// assert!(rwlock.try_write().is_ok());
/// }
/// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
@@ -555,22 +558,22 @@ impl<T: ?Sized> RwLock<T> {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let n = lock.read_owned().await;
/// assert_eq!(*n, 1);
/// let n = lock.read_owned().await;
/// assert_eq!(*n, 1);
///
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let r = c_lock.read_owned().await;
/// assert_eq!(*r, 1);
/// }).await.expect("The spawned task has panicked");
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let r = c_lock.read_owned().await;
/// assert_eq!(*r, 1);
/// }).await.expect("The spawned task has panicked");
///
/// // Drop the guard after the spawned task finishes.
/// drop(n);
/// // Drop the guard after the spawned task finishes.
/// drop(n);
///}
/// ```
pub async fn read_owned(self: Arc<Self>) -> OwnedRwLockReadGuard<T> {
@@ -631,23 +634,23 @@ impl<T: ?Sized> RwLock<T> {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let v = lock.try_read().unwrap();
/// assert_eq!(*v, 1);
/// let v = lock.try_read().unwrap();
/// assert_eq!(*v, 1);
///
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let n = c_lock.read().await;
/// assert_eq!(*n, 1);
/// }).await.expect("The spawned task has panicked");
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let n = c_lock.read().await;
/// assert_eq!(*n, 1);
/// }).await.expect("The spawned task has panicked");
///
/// // Drop the guard when spawned task finishes.
/// drop(v);
/// }
/// // Drop the guard when spawned task finishes.
/// drop(v);
/// # }
/// ```
pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, TryLockError> {
match self.s.try_acquire(1) {
@@ -696,23 +699,23 @@ impl<T: ?Sized> RwLock<T> {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let v = lock.try_read_owned().unwrap();
/// assert_eq!(*v, 1);
/// let v = lock.try_read_owned().unwrap();
/// assert_eq!(*v, 1);
///
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let n = c_lock.read_owned().await;
/// assert_eq!(*n, 1);
/// }).await.expect("The spawned task has panicked");
/// tokio::spawn(async move {
/// // While main has an active read lock, we acquire one too.
/// let n = c_lock.read_owned().await;
/// assert_eq!(*n, 1);
/// }).await.expect("The spawned task has panicked");
///
/// // Drop the guard when spawned task finishes.
/// drop(v);
/// }
/// // Drop the guard when spawned task finishes.
/// drop(v);
/// # }
/// ```
pub fn try_read_owned(self: Arc<Self>) -> Result<OwnedRwLockReadGuard<T>, TryLockError> {
match self.s.try_acquire(1) {
@@ -761,13 +764,13 @@ impl<T: ?Sized> RwLock<T> {
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = RwLock::new(1);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(1);
///
/// let mut n = lock.write().await;
/// *n = 2;
///}
/// let mut n = lock.write().await;
/// *n = 2;
/// # }
/// ```
pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
let acquire_fut = async {
@@ -831,6 +834,8 @@ impl<T: ?Sized> RwLock<T> {
/// # Examples
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::Arc;
/// use tokio::{sync::RwLock};
///
@@ -859,6 +864,7 @@ impl<T: ?Sized> RwLock<T> {
/// let read_lock = rwlock.try_read().unwrap();
/// assert_eq!(*read_lock, 2);
/// }
/// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
@@ -893,12 +899,12 @@ impl<T: ?Sized> RwLock<T> {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let lock = Arc::new(RwLock::new(1));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
///
/// let mut n = lock.write_owned().await;
/// *n = 2;
/// let mut n = lock.write_owned().await;
/// *n = 2;
///}
/// ```
pub async fn write_owned(self: Arc<Self>) -> OwnedRwLockWriteGuard<T> {
@@ -959,15 +965,15 @@ impl<T: ?Sized> RwLock<T> {
/// ```
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let rw = RwLock::new(1);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let rw = RwLock::new(1);
///
/// let v = rw.read().await;
/// assert_eq!(*v, 1);
/// let v = rw.read().await;
/// assert_eq!(*v, 1);
///
/// assert!(rw.try_write().is_err());
/// }
/// assert!(rw.try_write().is_err());
/// # }
/// ```
pub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError> {
match self.s.try_acquire(self.mr as usize) {
@@ -1017,15 +1023,15 @@ impl<T: ?Sized> RwLock<T> {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// #[tokio::main]
/// async fn main() {
/// let rw = Arc::new(RwLock::new(1));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let rw = Arc::new(RwLock::new(1));
///
/// let v = Arc::clone(&rw).read_owned().await;
/// assert_eq!(*v, 1);
/// let v = Arc::clone(&rw).read_owned().await;
/// assert_eq!(*v, 1);
///
/// assert!(rw.try_write_owned().is_err());
/// }
/// assert!(rw.try_write_owned().is_err());
/// # }
/// ```
pub fn try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError> {
match self.s.try_acquire(self.mr as usize) {
+3 -3
View File
@@ -62,7 +62,7 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockReadGuard<T, U> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -109,7 +109,7 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockReadGuard<T, U> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -150,7 +150,7 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockReadGuard<T, U> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
+6 -6
View File
@@ -69,7 +69,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -121,7 +121,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -193,7 +193,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -255,7 +255,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -337,7 +337,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
/// # use tokio::sync::RwLock;
/// # use std::sync::Arc;
/// #
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
///
@@ -399,7 +399,7 @@ impl<T: ?Sized> OwnedRwLockWriteGuard<T> {
/// use std::sync::Arc;
/// use tokio::sync::{RwLock, OwnedRwLockWriteGuard};
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
///
@@ -68,7 +68,7 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockMappedWriteGuard<T, U> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -119,7 +119,7 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockMappedWriteGuard<T, U> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(Foo(1)));
///
@@ -168,7 +168,7 @@ impl<T: ?Sized, U: ?Sized> OwnedRwLockMappedWriteGuard<T, U> {
/// OwnedRwLockMappedWriteGuard,
/// };
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
///
+2 -2
View File
@@ -66,7 +66,7 @@ impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
@@ -118,7 +118,7 @@ impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
+5 -5
View File
@@ -72,7 +72,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
@@ -130,7 +130,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
@@ -205,7 +205,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
@@ -274,7 +274,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
@@ -352,7 +352,7 @@ impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> {
/// # use tokio::sync::RwLock;
/// # use std::sync::Arc;
/// #
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
///
+2 -2
View File
@@ -69,7 +69,7 @@ impl<'a, T: ?Sized> RwLockMappedWriteGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
@@ -124,7 +124,7 @@ impl<'a, T: ?Sized> RwLockMappedWriteGuard<'a, T> {
/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// struct Foo(u32);
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = RwLock::new(Foo(1));
///
+115 -109
View File
@@ -33,18 +33,18 @@ use std::sync::Arc;
/// ```
/// use tokio::sync::{Semaphore, TryAcquireError};
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(3);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let semaphore = Semaphore::new(3);
///
/// let a_permit = semaphore.acquire().await.unwrap();
/// let two_permits = semaphore.acquire_many(2).await.unwrap();
/// let a_permit = semaphore.acquire().await.unwrap();
/// let two_permits = semaphore.acquire_many(2).await.unwrap();
///
/// assert_eq!(semaphore.available_permits(), 0);
/// assert_eq!(semaphore.available_permits(), 0);
///
/// let permit_attempt = semaphore.try_acquire();
/// assert_eq!(permit_attempt.err(), Some(TryAcquireError::NoPermits));
/// }
/// let permit_attempt = semaphore.try_acquire();
/// assert_eq!(permit_attempt.err(), Some(TryAcquireError::NoPermits));
/// # }
/// ```
///
/// ## Limit the number of simultaneously opened files in your program
@@ -61,6 +61,8 @@ use std::sync::Arc;
/// file, the program will wait until a permit becomes available before
/// proceeding to open another file.
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::io::Result;
/// use tokio::fs::File;
/// use tokio::sync::Semaphore;
@@ -74,6 +76,7 @@ use std::sync::Arc;
/// buffer.write_all(message).await?;
/// Ok(()) // Permit goes out of scope here, and is available again for acquisition
/// }
/// # }
/// ```
///
/// ## Limit the number of outgoing requests being sent at the same time
@@ -93,37 +96,37 @@ use std::sync::Arc;
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// // Define maximum number of parallel requests.
/// let semaphore = Arc::new(Semaphore::new(10));
/// // Spawn many tasks that will send requests.
/// let mut jhs = Vec::new();
/// for task_id in 0..100 {
/// let semaphore = semaphore.clone();
/// let jh = tokio::spawn(async move {
/// // Acquire permit before sending request.
/// let _permit = semaphore.acquire().await.unwrap();
/// // Send the request.
/// let response = send_request(task_id).await;
/// // Drop the permit after the request has been sent.
/// drop(_permit);
/// // Handle response.
/// // ...
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// // Define maximum number of parallel requests.
/// let semaphore = Arc::new(Semaphore::new(5));
/// // Spawn many tasks that will send requests.
/// let mut jhs = Vec::new();
/// for task_id in 0..50 {
/// let semaphore = semaphore.clone();
/// let jh = tokio::spawn(async move {
/// // Acquire permit before sending request.
/// let _permit = semaphore.acquire().await.unwrap();
/// // Send the request.
/// let response = send_request(task_id).await;
/// // Drop the permit after the request has been sent.
/// drop(_permit);
/// // Handle response.
/// // ...
///
/// response
/// });
/// jhs.push(jh);
/// }
/// // Collect responses from tasks.
/// let mut responses = Vec::new();
/// for jh in jhs {
/// let response = jh.await.unwrap();
/// responses.push(response);
/// }
/// // Process responses.
/// // ...
/// response
/// });
/// jhs.push(jh);
/// }
/// // Collect responses from tasks.
/// let mut responses = Vec::new();
/// for jh in jhs {
/// let response = jh.await.unwrap();
/// responses.push(response);
/// }
/// // Process responses.
/// // ...
/// # }
/// # async fn send_request(task_id: usize) {
/// # // Send request.
/// # }
@@ -144,6 +147,8 @@ use std::sync::Arc;
/// (Since our semaphore is not a global variable — if it was, then `acquire` would be enough.)
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
/// use tokio::net::TcpListener;
@@ -174,6 +179,7 @@ use std::sync::Arc;
/// # async fn handle_connection(_socket: &mut tokio::net::TcpStream) {
/// # // Do work
/// # }
/// # }
/// ```
///
/// ## Prevent tests from running in parallel
@@ -370,20 +376,20 @@ use std::sync::Arc;
/// }
/// }
///
/// #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn _hidden() {}
/// # #[tokio::main(flavor = "current_thread", start_paused = true)]
/// async fn main() {
/// let capacity = 5;
/// let update_interval = Duration::from_secs_f32(1.0 / capacity as f32);
/// let bucket = TokenBucket::new(update_interval, capacity);
/// # async fn main() {
/// let capacity = 5;
/// let update_interval = Duration::from_secs_f32(1.0 / capacity as f32);
/// let bucket = TokenBucket::new(update_interval, capacity);
///
/// for _ in 0..5 {
/// bucket.acquire().await;
/// for _ in 0..5 {
/// bucket.acquire().await;
///
/// // do the operation
/// }
/// // do the operation
/// }
/// # }
/// ```
///
/// [`PollSemaphore`]: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.PollSemaphore.html
@@ -559,19 +565,19 @@ impl Semaphore {
/// ```
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(2);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let semaphore = Semaphore::new(2);
///
/// let permit_1 = semaphore.acquire().await.unwrap();
/// assert_eq!(semaphore.available_permits(), 1);
/// let permit_1 = semaphore.acquire().await.unwrap();
/// assert_eq!(semaphore.available_permits(), 1);
///
/// let permit_2 = semaphore.acquire().await.unwrap();
/// assert_eq!(semaphore.available_permits(), 0);
/// let permit_2 = semaphore.acquire().await.unwrap();
/// assert_eq!(semaphore.available_permits(), 0);
///
/// drop(permit_1);
/// assert_eq!(semaphore.available_permits(), 1);
/// }
/// drop(permit_1);
/// assert_eq!(semaphore.available_permits(), 1);
/// # }
/// ```
///
/// [`AcquireError`]: crate::sync::AcquireError
@@ -612,13 +618,13 @@ impl Semaphore {
/// ```
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(5);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let semaphore = Semaphore::new(5);
///
/// let permit = semaphore.acquire_many(3).await.unwrap();
/// assert_eq!(semaphore.available_permits(), 2);
/// }
/// let permit = semaphore.acquire_many(3).await.unwrap();
/// assert_eq!(semaphore.available_permits(), 2);
/// # }
/// ```
///
/// [`AcquireError`]: crate::sync::AcquireError
@@ -735,24 +741,24 @@ impl Semaphore {
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(3));
/// let mut join_handles = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let semaphore = Arc::new(Semaphore::new(3));
/// let mut join_handles = Vec::new();
///
/// for _ in 0..5 {
/// let permit = semaphore.clone().acquire_owned().await.unwrap();
/// join_handles.push(tokio::spawn(async move {
/// // perform task...
/// // explicitly own `permit` in the task
/// drop(permit);
/// }));
/// }
///
/// for handle in join_handles {
/// handle.await.unwrap();
/// }
/// for _ in 0..5 {
/// let permit = semaphore.clone().acquire_owned().await.unwrap();
/// join_handles.push(tokio::spawn(async move {
/// // perform task...
/// // explicitly own `permit` in the task
/// drop(permit);
/// }));
/// }
///
/// for handle in join_handles {
/// handle.await.unwrap();
/// }
/// # }
/// ```
///
/// [`Arc`]: std::sync::Arc
@@ -796,24 +802,24 @@ impl Semaphore {
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(10));
/// let mut join_handles = Vec::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let semaphore = Arc::new(Semaphore::new(10));
/// let mut join_handles = Vec::new();
///
/// for _ in 0..5 {
/// let permit = semaphore.clone().acquire_many_owned(2).await.unwrap();
/// join_handles.push(tokio::spawn(async move {
/// // perform task...
/// // explicitly own `permit` in the task
/// drop(permit);
/// }));
/// }
///
/// for handle in join_handles {
/// handle.await.unwrap();
/// }
/// for _ in 0..5 {
/// let permit = semaphore.clone().acquire_many_owned(2).await.unwrap();
/// join_handles.push(tokio::spawn(async move {
/// // perform task...
/// // explicitly own `permit` in the task
/// drop(permit);
/// }));
/// }
///
/// for handle in join_handles {
/// handle.await.unwrap();
/// }
/// # }
/// ```
///
/// [`Arc`]: std::sync::Arc
@@ -936,23 +942,23 @@ impl Semaphore {
/// use std::sync::Arc;
/// use tokio::sync::TryAcquireError;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(1));
/// let semaphore2 = semaphore.clone();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let semaphore = Arc::new(Semaphore::new(1));
/// let semaphore2 = semaphore.clone();
///
/// tokio::spawn(async move {
/// let permit = semaphore.acquire_many(2).await;
/// assert!(permit.is_err());
/// println!("waiter received error");
/// });
/// tokio::spawn(async move {
/// let permit = semaphore.acquire_many(2).await;
/// assert!(permit.is_err());
/// println!("waiter received error");
/// });
///
/// println!("closing semaphore");
/// semaphore2.close();
/// println!("closing semaphore");
/// semaphore2.close();
///
/// // Cannot obtain more permits
/// assert_eq!(semaphore2.try_acquire().err(), Some(TryAcquireError::Closed))
/// }
/// // Cannot obtain more permits
/// assert_eq!(semaphore2.try_acquire().err(), Some(TryAcquireError::Closed))
/// # }
/// ```
pub fn close(&self) {
self.ll_sem.close();
+39 -39
View File
@@ -35,20 +35,20 @@ use std::task::Poll;
///
/// static ONCE: SetOnce<u32> = SetOnce::const_new();
///
/// #[tokio::main]
/// async fn main() -> Result<(), SetOnceError<u32>> {
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), SetOnceError<u32>> {
///
/// // set the value inside a task somewhere...
/// tokio::spawn(async move { ONCE.set(20) });
/// // set the value inside a task somewhere...
/// tokio::spawn(async move { ONCE.set(20) });
///
/// // checking with .get doesn't block main thread
/// println!("{:?}", ONCE.get());
/// // checking with .get doesn't block main thread
/// println!("{:?}", ONCE.get());
///
/// // wait until the value is set, blocks the thread
/// println!("{:?}", ONCE.wait().await);
/// // wait until the value is set, blocks the thread
/// println!("{:?}", ONCE.wait().await);
///
/// Ok(())
/// }
/// Ok(())
/// # }
/// ```
///
/// A `SetOnce` is typically used for global variables that need to be
@@ -61,30 +61,30 @@ use std::task::Poll;
/// use tokio::sync::{SetOnce, SetOnceError};
/// use std::sync::Arc;
///
/// #[tokio::main]
/// async fn main() -> Result<(), SetOnceError<u32>> {
/// let once = SetOnce::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), SetOnceError<u32>> {
/// let once = SetOnce::new();
///
/// let arc = Arc::new(once);
/// let first_cl = Arc::clone(&arc);
/// let second_cl = Arc::clone(&arc);
/// let arc = Arc::new(once);
/// let first_cl = Arc::clone(&arc);
/// let second_cl = Arc::clone(&arc);
///
/// // set the value inside a task
/// tokio::spawn(async move { first_cl.set(20) }).await.unwrap()?;
/// // set the value inside a task
/// tokio::spawn(async move { first_cl.set(20) }).await.unwrap()?;
///
/// // wait inside task to not block the main thread
/// tokio::spawn(async move {
/// // wait inside async context for the value to be set
/// assert_eq!(*second_cl.wait().await, 20);
/// }).await.unwrap();
/// // wait inside task to not block the main thread
/// tokio::spawn(async move {
/// // wait inside async context for the value to be set
/// assert_eq!(*second_cl.wait().await, 20);
/// }).await.unwrap();
///
/// // subsequent set calls will fail
/// assert!(arc.set(30).is_err());
/// // subsequent set calls will fail
/// assert!(arc.set(30).is_err());
///
/// println!("{:?}", arc.get());
/// println!("{:?}", arc.get());
///
/// Ok(())
/// }
/// Ok(())
/// # }
/// ```
///
/// [`asyncio.Event`]: https://docs.python.org/3/library/asyncio-sync.html#asyncio.Event
@@ -175,13 +175,13 @@ impl<T> SetOnce<T> {
/// Ok(ONCE.get())
/// }
///
/// #[tokio::main]
/// async fn main() -> Result<(), SetOnceError<u32>> {
/// let result = get_global_integer()?;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), SetOnceError<u32>> {
/// let result = get_global_integer()?;
///
/// assert_eq!(result, Some(&2));
/// Ok(())
/// }
/// assert_eq!(result, Some(&2));
/// Ok(())
/// # }
/// ```
///
/// [`tokio-console`]: https://github.com/tokio-rs/console
@@ -226,12 +226,12 @@ impl<T> SetOnce<T> {
/// ONCE.get()
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let result = get_global_integer();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let result = get_global_integer();
///
/// assert_eq!(result, Some(&1));
/// }
/// assert_eq!(result, Some(&1));
/// # }
/// ```
///
/// [`tokio-console`]: https://github.com/tokio-rs/console
+119 -119
View File
@@ -111,25 +111,25 @@
//! ```
//! use tokio::sync::watch;
//!
//! #[tokio::main]
//! async fn main() {
//! let (tx, mut rx) = watch::channel("hello");
//! tx.send("goodbye").unwrap();
//! drop(tx);
//! #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let (tx, mut rx) = watch::channel("hello");
//! tx.send("goodbye").unwrap();
//! drop(tx);
//!
//! // `has_changed` does not mark the value as seen and errors
//! // since the channel is closed.
//! assert!(rx.has_changed().is_err());
//! // `has_changed` does not mark the value as seen and errors
//! // since the channel is closed.
//! assert!(rx.has_changed().is_err());
//!
//! // `changed` returns Ok since the value is not already marked as seen
//! // even if the channel is closed.
//! assert!(rx.changed().await.is_ok());
//! // `changed` returns Ok since the value is not already marked as seen
//! // even if the channel is closed.
//! assert!(rx.changed().await.is_ok());
//!
//! // The `changed` call above marks the value as seen.
//! // The next `changed` call now returns an error as the channel is closed
//! // AND the current value is seen.
//! assert!(rx.changed().await.is_err());
//! }
//! // The `changed` call above marks the value as seen.
//! // The next `changed` call now returns an error as the channel is closed
//! // AND the current value is seen.
//! assert!(rx.changed().await.is_err());
//! # }
//! ```
//!
//! # Closing
@@ -258,35 +258,35 @@ impl<'a, T> Ref<'a, T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = watch::channel("hello");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = watch::channel("hello");
///
/// tx.send("goodbye").unwrap();
/// // The sender does never consider the value as changed.
/// assert!(!tx.borrow().has_changed());
/// tx.send("goodbye").unwrap();
/// // The sender does never consider the value as changed.
/// assert!(!tx.borrow().has_changed());
///
/// // Drop the sender immediately, just for testing purposes.
/// drop(tx);
/// // Drop the sender immediately, just for testing purposes.
/// drop(tx);
///
/// // Even if the sender has already been dropped...
/// assert!(rx.has_changed().is_err());
/// // ...the modified value is still readable and detected as changed.
/// assert_eq!(*rx.borrow(), "goodbye");
/// assert!(rx.borrow().has_changed());
/// // Even if the sender has already been dropped...
/// assert!(rx.has_changed().is_err());
/// // ...the modified value is still readable and detected as changed.
/// assert_eq!(*rx.borrow(), "goodbye");
/// assert!(rx.borrow().has_changed());
///
/// // Read the changed value and mark it as seen.
/// {
/// let received = rx.borrow_and_update();
/// assert_eq!(*received, "goodbye");
/// assert!(received.has_changed());
/// // Release the read lock when leaving this scope.
/// }
///
/// // Now the value has already been marked as seen and could
/// // never be modified again (after the sender has been dropped).
/// assert!(!rx.borrow().has_changed());
/// // Read the changed value and mark it as seen.
/// {
/// let received = rx.borrow_and_update();
/// assert_eq!(*received, "goodbye");
/// assert!(received.has_changed());
/// // Release the read lock when leaving this scope.
/// }
///
/// // Now the value has already been marked as seen and could
/// // never be modified again (after the sender has been dropped).
/// assert!(!rx.borrow().has_changed());
/// # }
/// ```
pub fn has_changed(&self) -> bool {
self.has_changed
@@ -705,18 +705,18 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = watch::channel("hello");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = watch::channel("hello");
///
/// tx.send("goodbye").unwrap();
/// tx.send("goodbye").unwrap();
///
/// assert!(rx.has_changed().unwrap());
/// assert_eq!(*rx.borrow_and_update(), "goodbye");
/// assert!(rx.has_changed().unwrap());
/// assert_eq!(*rx.borrow_and_update(), "goodbye");
///
/// // The value has been marked as seen
/// assert!(!rx.has_changed().unwrap());
/// }
/// // The value has been marked as seen
/// assert!(!rx.has_changed().unwrap());
/// # }
/// ```
///
/// ## Closed channel example
@@ -724,16 +724,16 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = watch::channel("hello");
/// tx.send("goodbye").unwrap();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = watch::channel("hello");
/// tx.send("goodbye").unwrap();
///
/// drop(tx);
/// drop(tx);
///
/// // The channel is closed
/// assert!(rx.has_changed().is_err());
/// }
/// // The channel is closed
/// assert!(rx.has_changed().is_err());
/// # }
/// ```
pub fn has_changed(&self) -> Result<bool, error::RecvError> {
// Load the version from the state
@@ -800,20 +800,20 @@ impl<T> Receiver<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, mut rx) = watch::channel("hello");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, mut rx) = watch::channel("hello");
///
/// tokio::spawn(async move {
/// tx.send("goodbye").unwrap();
/// });
/// tokio::spawn(async move {
/// tx.send("goodbye").unwrap();
/// });
///
/// assert!(rx.changed().await.is_ok());
/// assert_eq!(*rx.borrow_and_update(), "goodbye");
/// assert!(rx.changed().await.is_ok());
/// assert_eq!(*rx.borrow_and_update(), "goodbye");
///
/// // The `tx` handle has been dropped
/// assert!(rx.changed().await.is_err());
/// }
/// // The `tx` handle has been dropped
/// assert!(rx.changed().await.is_err());
/// # }
/// ```
pub async fn changed(&mut self) -> Result<(), error::RecvError> {
cooperative(changed_impl(&self.shared, &mut self.version)).await
@@ -1296,19 +1296,19 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx) = watch::channel("hello");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx) = watch::channel("hello");
///
/// tokio::spawn(async move {
/// // use `rx`
/// drop(rx);
/// });
/// tokio::spawn(async move {
/// // use `rx`
/// drop(rx);
/// });
///
/// // Waits for `rx` to drop
/// tx.closed().await;
/// println!("the `rx` handles dropped")
/// }
/// // Waits for `rx` to drop
/// tx.closed().await;
/// println!("the `rx` handles dropped")
/// # }
/// ```
pub async fn closed(&self) {
cooperative(async {
@@ -1344,18 +1344,18 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx) = watch::channel(0u64);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx) = watch::channel(0u64);
///
/// tx.send(5).unwrap();
/// tx.send(5).unwrap();
///
/// let rx = tx.subscribe();
/// assert_eq!(5, *rx.borrow());
/// let rx = tx.subscribe();
/// assert_eq!(5, *rx.borrow());
///
/// tx.send(10).unwrap();
/// assert_eq!(10, *rx.borrow());
/// }
/// tx.send(10).unwrap();
/// assert_eq!(10, *rx.borrow());
/// # }
/// ```
///
/// The most recent message is considered seen by the channel, so this test
@@ -1365,24 +1365,24 @@ impl<T> Sender<T> {
/// use tokio::sync::watch;
/// use tokio::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, _rx) = watch::channel(0u64);
/// tx.send(5).unwrap();
/// let mut rx = tx.subscribe();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, _rx) = watch::channel(0u64);
/// tx.send(5).unwrap();
/// let mut rx = tx.subscribe();
///
/// tokio::spawn(async move {
/// // by spawning and sleeping, the message is sent after `main`
/// // hits the call to `changed`.
/// # if false {
/// tokio::time::sleep(Duration::from_millis(10)).await;
/// # }
/// tx.send(100).unwrap();
/// });
/// tokio::spawn(async move {
/// // by spawning and sleeping, the message is sent after `main`
/// // hits the call to `changed`.
/// # if false {
/// tokio::time::sleep(Duration::from_millis(10)).await;
/// # }
/// tx.send(100).unwrap();
/// });
///
/// rx.changed().await.unwrap();
/// assert_eq!(100, *rx.borrow());
/// }
/// rx.changed().await.unwrap();
/// assert_eq!(100, *rx.borrow());
/// # }
/// ```
pub fn subscribe(&self) -> Receiver<T> {
let shared = self.shared.clone();
@@ -1400,16 +1400,16 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx, rx1) = watch::channel("hello");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx, rx1) = watch::channel("hello");
///
/// assert_eq!(1, tx.receiver_count());
/// assert_eq!(1, tx.receiver_count());
///
/// let mut _rx2 = rx1.clone();
/// let mut _rx2 = rx1.clone();
///
/// assert_eq!(2, tx.receiver_count());
/// }
/// assert_eq!(2, tx.receiver_count());
/// # }
/// ```
pub fn receiver_count(&self) -> usize {
self.shared.ref_count_rx.load(Relaxed)
@@ -1422,17 +1422,17 @@ impl<T> Sender<T> {
/// ```
/// use tokio::sync::watch;
///
/// #[tokio::main]
/// async fn main() {
/// let (tx1, rx) = watch::channel("hello");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let (tx1, rx) = watch::channel("hello");
///
/// assert_eq!(1, tx1.sender_count());
/// assert_eq!(1, tx1.sender_count());
///
/// let tx2 = tx1.clone();
/// let tx2 = tx1.clone();
///
/// assert_eq!(2, tx1.sender_count());
/// assert_eq!(2, tx2.sender_count());
/// }
/// assert_eq!(2, tx1.sender_count());
/// assert_eq!(2, tx2.sender_count());
/// # }
/// ```
pub fn sender_count(&self) -> usize {
self.shared.ref_count_tx.load(Relaxed)
+1 -1
View File
@@ -37,7 +37,7 @@
//! Tokio. For example:
//!
//! ```
//! # #[tokio::main]
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! use tokio::{task, sync::mpsc};
//!
+59 -56
View File
@@ -31,24 +31,24 @@ use crate::util::IdleNotifiedSet;
/// ```
/// use tokio::task::JoinSet;
///
/// #[tokio::main]
/// async fn main() {
/// let mut set = JoinSet::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut set = JoinSet::new();
///
/// for i in 0..10 {
/// set.spawn(async move { i });
/// }
///
/// let mut seen = [false; 10];
/// while let Some(res) = set.join_next().await {
/// let idx = res.unwrap();
/// seen[idx] = true;
/// }
///
/// for i in 0..10 {
/// assert!(seen[i]);
/// }
/// for i in 0..10 {
/// set.spawn(async move { i });
/// }
///
/// let mut seen = [false; 10];
/// while let Some(res) = set.join_next().await {
/// let idx = res.unwrap();
/// seen[idx] = true;
/// }
///
/// for i in 0..10 {
/// assert!(seen[i]);
/// }
/// # }
/// ```
///
/// # Task ID guarantees
@@ -219,6 +219,8 @@ impl<T: 'static> JoinSet<T> {
/// Spawn multiple blocking tasks and wait for them.
///
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::task::JoinSet;
///
/// #[tokio::main]
@@ -239,6 +241,7 @@ impl<T: 'static> JoinSet<T> {
/// assert!(seen[i]);
/// }
/// }
/// # }
/// ```
///
/// # Panics
@@ -396,20 +399,20 @@ impl<T: 'static> JoinSet<T> {
/// use tokio::task::JoinSet;
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let mut set = JoinSet::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut set = JoinSet::new();
///
/// for i in 0..3 {
/// set.spawn(async move {
/// tokio::time::sleep(Duration::from_secs(3 - i)).await;
/// i
/// });
/// }
///
/// let output = set.join_all().await;
/// assert_eq!(output, vec![2, 1, 0]);
/// for i in 0..3 {
/// set.spawn(async move {
/// tokio::time::sleep(Duration::from_secs(3 - i)).await;
/// i
/// });
/// }
///
/// let output = set.join_all().await;
/// assert_eq!(output, vec![2, 1, 0]);
/// # }
/// ```
///
/// Equivalent implementation of `join_all`, using [`join_next`] and loop.
@@ -418,24 +421,24 @@ impl<T: 'static> JoinSet<T> {
/// use tokio::task::JoinSet;
/// use std::panic;
///
/// #[tokio::main]
/// async fn main() {
/// let mut set = JoinSet::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut set = JoinSet::new();
///
/// for i in 0..3 {
/// set.spawn(async move {i});
/// }
///
/// let mut output = Vec::new();
/// while let Some(res) = set.join_next().await{
/// match res {
/// Ok(t) => output.push(t),
/// Err(err) if err.is_panic() => panic::resume_unwind(err.into_panic()),
/// Err(err) => panic!("{err}"),
/// }
/// }
/// assert_eq!(output.len(),3);
/// for i in 0..3 {
/// set.spawn(async move {i});
/// }
///
/// let mut output = Vec::new();
/// while let Some(res) = set.join_next().await{
/// match res {
/// Ok(t) => output.push(t),
/// Err(err) if err.is_panic() => panic::resume_unwind(err.into_panic()),
/// Err(err) => panic!("{err}"),
/// }
/// }
/// assert_eq!(output.len(),3);
/// # }
/// ```
/// [`join_next`]: fn@Self::join_next
/// [`JoinError::id`]: fn@crate::task::JoinError::id
@@ -613,20 +616,20 @@ impl<T> Default for JoinSet<T> {
/// ```
/// use tokio::task::JoinSet;
///
/// #[tokio::main]
/// async fn main() {
/// let mut set: JoinSet<_> = (0..10).map(|i| async move { i }).collect();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut set: JoinSet<_> = (0..10).map(|i| async move { i }).collect();
///
/// let mut seen = [false; 10];
/// while let Some(res) = set.join_next().await {
/// let idx = res.unwrap();
/// seen[idx] = true;
/// }
///
/// for i in 0..10 {
/// assert!(seen[i]);
/// }
/// let mut seen = [false; 10];
/// while let Some(res) = set.join_next().await {
/// let idx = res.unwrap();
/// seen[idx] = true;
/// }
///
/// for i in 0..10 {
/// assert!(seen[i]);
/// }
/// # }
/// ```
///
/// [`collect`]: std::iter::Iterator::collect
+88 -82
View File
@@ -64,24 +64,24 @@ cfg_rt! {
/// use std::rc::Rc;
/// use tokio::task;
///
/// #[tokio::main]
/// async fn main() {
/// let nonsend_data = Rc::new("my nonsend data...");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let nonsend_data = Rc::new("my nonsend data...");
///
/// // Construct a local task set that can run `!Send` futures.
/// let local = task::LocalSet::new();
/// // Construct a local task set that can run `!Send` futures.
/// let local = task::LocalSet::new();
///
/// // Run the local task set.
/// local.run_until(async move {
/// let nonsend_data = nonsend_data.clone();
/// // `spawn_local` ensures that the future is spawned on the local
/// // task set.
/// task::spawn_local(async move {
/// println!("{}", nonsend_data);
/// // ...
/// }).await.unwrap();
/// }).await;
/// }
/// // Run the local task set.
/// local.run_until(async move {
/// let nonsend_data = nonsend_data.clone();
/// // `spawn_local` ensures that the future is spawned on the local
/// // task set.
/// task::spawn_local(async move {
/// println!("{}", nonsend_data);
/// // ...
/// }).await.unwrap();
/// }).await;
/// # }
/// ```
/// **Note:** The `run_until` method can only be used in `#[tokio::main]`,
/// `#[tokio::test]` or directly inside a call to [`Runtime::block_on`]. It
@@ -98,26 +98,26 @@ cfg_rt! {
/// use tokio::{task, time};
/// use std::rc::Rc;
///
/// #[tokio::main]
/// async fn main() {
/// let nonsend_data = Rc::new("world");
/// let local = task::LocalSet::new();
///
/// let nonsend_data2 = nonsend_data.clone();
/// local.spawn_local(async move {
/// // ...
/// println!("hello {}", nonsend_data2)
/// });
///
/// local.spawn_local(async move {
/// time::sleep(time::Duration::from_millis(100)).await;
/// println!("goodbye {}", nonsend_data)
/// });
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let nonsend_data = Rc::new("world");
/// let local = task::LocalSet::new();
///
/// let nonsend_data2 = nonsend_data.clone();
/// local.spawn_local(async move {
/// // ...
/// println!("hello {}", nonsend_data2)
/// });
///
/// local.await;
/// }
/// local.spawn_local(async move {
/// time::sleep(time::Duration::from_millis(100)).await;
/// println!("goodbye {}", nonsend_data)
/// });
///
/// // ...
///
/// local.await;
/// # }
/// ```
/// **Note:** Awaiting a `LocalSet` can only be done inside
/// `#[tokio::main]`, `#[tokio::test]` or directly inside a call to
@@ -133,6 +133,8 @@ cfg_rt! {
///
/// The following example puts the `LocalSet` inside a new thread.
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Builder;
/// use tokio::sync::{mpsc, oneshot};
/// use tokio::task::LocalSet;
@@ -212,6 +214,7 @@ cfg_rt! {
/// let eleven = response.await.unwrap();
/// assert_eq!(eleven, 11);
/// }
/// # }
/// ```
///
/// [`Send`]: trait@std::marker::Send
@@ -354,21 +357,21 @@ cfg_rt! {
/// use std::rc::Rc;
/// use tokio::task;
///
/// #[tokio::main]
/// async fn main() {
/// let nonsend_data = Rc::new("my nonsend data...");
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let nonsend_data = Rc::new("my nonsend data...");
///
/// let local = task::LocalSet::new();
/// let local = task::LocalSet::new();
///
/// // Run the local task set.
/// local.run_until(async move {
/// let nonsend_data = nonsend_data.clone();
/// task::spawn_local(async move {
/// println!("{}", nonsend_data);
/// // ...
/// }).await.unwrap();
/// }).await;
/// }
/// // Run the local task set.
/// local.run_until(async move {
/// let nonsend_data = nonsend_data.clone();
/// task::spawn_local(async move {
/// println!("{}", nonsend_data);
/// // ...
/// }).await.unwrap();
/// }).await;
/// # }
/// ```
///
/// [`LocalSet`]: struct@crate::task::LocalSet
@@ -543,31 +546,31 @@ impl LocalSet {
/// ```rust
/// use tokio::task;
///
/// #[tokio::main]
/// async fn main() {
/// let local = task::LocalSet::new();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let local = task::LocalSet::new();
///
/// // Spawn a future on the local set. This future will be run when
/// // we call `run_until` to drive the task set.
/// local.spawn_local(async {
/// // ...
/// });
/// // Spawn a future on the local set. This future will be run when
/// // we call `run_until` to drive the task set.
/// local.spawn_local(async {
/// // ...
/// });
///
/// // Run the local task set.
/// local.run_until(async move {
/// // ...
/// }).await;
/// // Run the local task set.
/// local.run_until(async move {
/// // ...
/// }).await;
///
/// // When `run` finishes, we can spawn _more_ futures, which will
/// // run in subsequent calls to `run_until`.
/// local.spawn_local(async {
/// // ...
/// });
/// // When `run` finishes, we can spawn _more_ futures, which will
/// // run in subsequent calls to `run_until`.
/// local.spawn_local(async {
/// // ...
/// });
///
/// local.run_until(async move {
/// // ...
/// }).await;
/// }
/// local.run_until(async move {
/// // ...
/// }).await;
/// # }
/// ```
/// [`spawn_local`]: fn@spawn_local
#[track_caller]
@@ -608,7 +611,7 @@ impl LocalSet {
/// issued from a local task, the [`spawn_blocking`] API may be used instead.
///
/// For example, this will panic:
/// ```should_panic
/// ```should_panic,ignore-wasm
/// use tokio::runtime::Runtime;
/// use tokio::task;
///
@@ -626,6 +629,8 @@ impl LocalSet {
/// ```
/// This, however, will not panic:
/// ```
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::runtime::Runtime;
/// use tokio::task;
///
@@ -640,6 +645,7 @@ impl LocalSet {
/// });
/// join.await.unwrap();
/// })
/// # }
/// ```
///
/// [`spawn_local`]: fn@spawn_local
@@ -675,15 +681,15 @@ impl LocalSet {
/// ```rust
/// use tokio::task;
///
/// #[tokio::main]
/// async fn main() {
/// task::LocalSet::new().run_until(async {
/// task::spawn_local(async move {
/// // ...
/// }).await.unwrap();
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// task::LocalSet::new().run_until(async {
/// task::spawn_local(async move {
/// // ...
/// }).await;
/// }
/// }).await.unwrap();
/// // ...
/// }).await;
/// # }
/// ```
///
/// [`spawn_local`]: fn@spawn_local
@@ -863,7 +869,7 @@ cfg_unstable! {
/// ```should_panic
/// use tokio::runtime::UnhandledPanic;
///
/// # #[tokio::main]
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// tokio::task::LocalSet::new()
/// .unhandled_panic(UnhandledPanic::ShutdownRuntime)
@@ -897,11 +903,11 @@ cfg_unstable! {
/// ```rust
/// use tokio::task;
///
/// #[tokio::main]
/// async fn main() {
/// let local_set = task::LocalSet::new();
/// println!("Local set id: {}", local_set.id());
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let local_set = task::LocalSet::new();
/// println!("Local set id: {}", local_set.id());
/// # }
/// ```
///
/// **Note**: This is an [unstable API][unstable]. The public API of this type
+10 -2
View File
@@ -70,7 +70,8 @@
//! ```
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let join = task::spawn(async {
//! // ...
//! "hello world!"
@@ -90,6 +91,8 @@
//! example:
//!
//! ```
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
@@ -100,6 +103,7 @@
//! // The returned result indicates that the task failed.
//! assert!(join.await.is_err());
//! # }
//! # }
//! ```
//!
//! `spawn`, `JoinHandle`, and `JoinError` are present when the "rt"
@@ -221,6 +225,8 @@
//! For example:
//!
//! ```
//! # #[cfg(not(target_family = "wasm"))]
//! # {
//! use tokio::task;
//!
//! # async fn docs() {
@@ -231,6 +237,7 @@
//!
//! assert_eq!(result, "blocking completed");
//! # }
//! # }
//! ```
//!
//! #### `yield_now`
@@ -245,7 +252,8 @@
//! ```rust
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! async {
//! task::spawn(async {
//! // ...
+14 -11
View File
@@ -35,6 +35,8 @@ cfg_rt! {
/// that processes each received connection.
///
/// ```no_run
/// # #[cfg(not(target_family = "wasm"))]
/// # {
/// use tokio::net::{TcpListener, TcpStream};
///
/// use std::io;
@@ -57,6 +59,7 @@ cfg_rt! {
/// });
/// }
/// }
/// # }
/// ```
///
/// To run multiple tasks in parallel and receive their results, join
@@ -112,18 +115,18 @@ cfg_rt! {
/// # drop(rc);
/// }
///
/// #[tokio::main]
/// async fn main() {
/// tokio::spawn(async {
/// // Force the `Rc` to stay in a scope with no `.await`
/// {
/// let rc = Rc::new(());
/// use_rc(rc.clone());
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// tokio::spawn(async {
/// // Force the `Rc` to stay in a scope with no `.await`
/// {
/// let rc = Rc::new(());
/// use_rc(rc.clone());
/// }
///
/// task::yield_now().await;
/// }).await.unwrap();
/// }
/// task::yield_now().await;
/// }).await.unwrap();
/// # }
/// ```
///
/// This will **not** work:
+22 -22
View File
@@ -81,14 +81,14 @@ impl Instant {
/// ```
/// use tokio::time::{Duration, Instant, sleep};
///
/// #[tokio::main]
/// async fn main() {
/// let now = Instant::now();
/// sleep(Duration::new(1, 0)).await;
/// let new_now = Instant::now();
/// println!("{:?}", new_now.checked_duration_since(now));
/// println!("{:?}", now.checked_duration_since(new_now)); // None
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let now = Instant::now();
/// sleep(Duration::new(1, 0)).await;
/// let new_now = Instant::now();
/// println!("{:?}", new_now.checked_duration_since(now));
/// println!("{:?}", now.checked_duration_since(new_now)); // None
/// # }
/// ```
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
self.std.checked_duration_since(earlier.std)
@@ -102,13 +102,13 @@ impl Instant {
/// ```
/// use tokio::time::{Duration, Instant, sleep};
///
/// #[tokio::main]
/// async fn main() {
/// let now = Instant::now();
/// sleep(Duration::new(1, 0)).await;
/// let new_now = Instant::now();
/// println!("{:?}", new_now.saturating_duration_since(now));
/// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let now = Instant::now();
/// sleep(Duration::new(1, 0)).await;
/// let new_now = Instant::now();
/// println!("{:?}", new_now.saturating_duration_since(now));
/// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
/// }
/// ```
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
@@ -123,13 +123,13 @@ impl Instant {
/// ```
/// use tokio::time::{Duration, Instant, sleep};
///
/// #[tokio::main]
/// async fn main() {
/// let instant = Instant::now();
/// let three_secs = Duration::from_secs(3);
/// sleep(three_secs).await;
/// assert!(instant.elapsed() >= three_secs);
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let instant = Instant::now();
/// let three_secs = Duration::from_secs(3);
/// sleep(three_secs).await;
/// assert!(instant.elapsed() >= three_secs);
/// # }
/// ```
pub fn elapsed(&self) -> Duration {
Instant::now().saturating_duration_since(*self)
+84 -84
View File
@@ -26,16 +26,16 @@ use std::task::{ready, Context, Poll};
/// ```
/// use tokio::time::{self, Duration};
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(Duration::from_millis(10));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(Duration::from_millis(10));
///
/// interval.tick().await; // ticks immediately
/// interval.tick().await; // ticks after 10ms
/// interval.tick().await; // ticks after 10ms
/// interval.tick().await; // ticks immediately
/// interval.tick().await; // ticks after 10ms
/// interval.tick().await; // ticks after 10ms
///
/// // approximately 20ms have elapsed.
/// }
/// // approximately 20ms have elapsed.
/// # }
/// ```
///
/// A simple example using `interval` to execute a task every two seconds.
@@ -57,14 +57,14 @@ use std::task::{ready, Context, Poll};
/// time::sleep(time::Duration::from_secs(1)).await
/// }
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(time::Duration::from_secs(2));
/// for _i in 0..5 {
/// interval.tick().await;
/// task_that_takes_a_second().await;
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(time::Duration::from_secs(2));
/// for _i in 0..5 {
/// interval.tick().await;
/// task_that_takes_a_second().await;
/// }
/// # }
/// ```
///
/// [`sleep`]: crate::time::sleep()
@@ -92,17 +92,17 @@ pub fn interval(period: Duration) -> Interval {
/// ```
/// use tokio::time::{interval_at, Duration, Instant};
///
/// #[tokio::main]
/// async fn main() {
/// let start = Instant::now() + Duration::from_millis(50);
/// let mut interval = interval_at(start, Duration::from_millis(10));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let start = Instant::now() + Duration::from_millis(50);
/// let mut interval = interval_at(start, Duration::from_millis(10));
///
/// interval.tick().await; // ticks after 50ms
/// interval.tick().await; // ticks after 10ms
/// interval.tick().await; // ticks after 10ms
/// interval.tick().await; // ticks after 50ms
/// interval.tick().await; // ticks after 10ms
/// interval.tick().await; // ticks after 10ms
///
/// // approximately 70ms have elapsed.
/// }
/// // approximately 70ms have elapsed.
/// # }
/// ```
#[track_caller]
pub fn interval_at(start: Instant, period: Duration) -> Interval {
@@ -155,16 +155,16 @@ fn internal_interval_at(
/// use tokio::time::{self, Duration};
/// # async fn task_that_takes_one_to_three_millis() {}
///
/// #[tokio::main]
/// async fn main() {
/// // ticks every 2 milliseconds
/// let mut interval = time::interval(Duration::from_millis(2));
/// for _ in 0..5 {
/// interval.tick().await;
/// // if this takes more than 2 milliseconds, a tick will be delayed
/// task_that_takes_one_to_three_millis().await;
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// // ticks every 2 milliseconds
/// let mut interval = time::interval(Duration::from_millis(2));
/// for _ in 0..5 {
/// interval.tick().await;
/// // if this takes more than 2 milliseconds, a tick will be delayed
/// task_that_takes_one_to_three_millis().await;
/// }
/// # }
/// ```
///
/// Generally, a tick is missed if too much time is spent without calling
@@ -418,17 +418,17 @@ impl Interval {
///
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(Duration::from_millis(10));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(Duration::from_millis(10));
///
/// interval.tick().await;
/// // approximately 0ms have elapsed. The first tick completes immediately.
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
/// // approximately 0ms have elapsed. The first tick completes immediately.
/// interval.tick().await;
/// interval.tick().await;
///
/// // approximately 20ms have elapsed.
/// }
/// // approximately 20ms have elapsed.
/// # }
/// ```
pub async fn tick(&mut self) -> Instant {
#[cfg(all(tokio_unstable, feature = "tracing"))]
@@ -506,20 +506,20 @@ impl Interval {
///
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
///
/// interval.tick().await;
/// interval.tick().await;
///
/// time::sleep(Duration::from_millis(50)).await;
/// interval.reset();
/// time::sleep(Duration::from_millis(50)).await;
/// interval.reset();
///
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
///
/// // approximately 250ms have elapsed.
/// }
/// // approximately 250ms have elapsed.
/// # }
/// ```
pub fn reset(&mut self) {
self.delay.as_mut().reset(Instant::now() + self.period);
@@ -538,20 +538,20 @@ impl Interval {
///
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
///
/// interval.tick().await;
/// interval.tick().await;
///
/// time::sleep(Duration::from_millis(50)).await;
/// interval.reset_immediately();
/// time::sleep(Duration::from_millis(50)).await;
/// interval.reset_immediately();
///
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
///
/// // approximately 150ms have elapsed.
/// }
/// // approximately 150ms have elapsed.
/// # }
/// ```
pub fn reset_immediately(&mut self) {
self.delay.as_mut().reset(Instant::now());
@@ -570,21 +570,21 @@ impl Interval {
///
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
/// interval.tick().await;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
/// interval.tick().await;
///
/// time::sleep(Duration::from_millis(50)).await;
/// time::sleep(Duration::from_millis(50)).await;
///
/// let after = Duration::from_millis(20);
/// interval.reset_after(after);
/// let after = Duration::from_millis(20);
/// interval.reset_after(after);
///
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
///
/// // approximately 170ms have elapsed.
/// }
/// // approximately 170ms have elapsed.
/// # }
/// ```
pub fn reset_after(&mut self, after: Duration) {
self.delay.as_mut().reset(Instant::now() + after);
@@ -606,21 +606,21 @@ impl Interval {
///
/// use std::time::Duration;
///
/// #[tokio::main]
/// async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
/// interval.tick().await;
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut interval = time::interval(Duration::from_millis(100));
/// interval.tick().await;
///
/// time::sleep(Duration::from_millis(50)).await;
/// time::sleep(Duration::from_millis(50)).await;
///
/// let deadline = Instant::now() + Duration::from_millis(30);
/// interval.reset_at(deadline);
/// let deadline = Instant::now() + Duration::from_millis(30);
/// interval.reset_at(deadline);
///
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
/// interval.tick().await;
///
/// // approximately 180ms have elapsed.
/// }
/// // approximately 180ms have elapsed.
/// # }
/// ```
pub fn reset_at(&mut self, deadline: Instant) {
self.delay.as_mut().reset(deadline);
+12 -12
View File
@@ -27,11 +27,11 @@
//! use std::time::Duration;
//! use tokio::time::sleep;
//!
//! #[tokio::main]
//! async fn main() {
//! sleep(Duration::from_millis(100)).await;
//! println!("100 ms have elapsed");
//! }
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! sleep(Duration::from_millis(100)).await;
//! println!("100 ms have elapsed");
//! # }
//! ```
//!
//! Require that an operation takes no more than 1s.
@@ -71,14 +71,14 @@
//! time::sleep(time::Duration::from_secs(1)).await
//! }
//!
//! #[tokio::main]
//! async fn main() {
//! let mut interval = time::interval(time::Duration::from_secs(2));
//! for _i in 0..5 {
//! interval.tick().await;
//! task_that_takes_a_second().await;
//! }
//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! let mut interval = time::interval(time::Duration::from_secs(2));
//! for _i in 0..5 {
//! interval.tick().await;
//! task_that_takes_a_second().await;
//! }
//! # }
//! ```
//!
//! [`interval`]: crate::time::interval()
+26 -26
View File
@@ -28,11 +28,11 @@ use std::task::{self, ready, Poll};
/// ```
/// use tokio::time::{sleep_until, Instant, Duration};
///
/// #[tokio::main]
/// async fn main() {
/// sleep_until(Instant::now() + Duration::from_millis(100)).await;
/// println!("100 ms have elapsed");
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// sleep_until(Instant::now() + Duration::from_millis(100)).await;
/// println!("100 ms have elapsed");
/// # }
/// ```
///
/// See the documentation for the [`Sleep`] type for more examples.
@@ -88,11 +88,11 @@ pub fn sleep_until(deadline: Instant) -> Sleep {
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
/// sleep(Duration::from_millis(100)).await;
/// println!("100 ms have elapsed");
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// sleep(Duration::from_millis(100)).await;
/// println!("100 ms have elapsed");
/// # }
/// ```
///
/// See the documentation for the [`Sleep`] type for more examples.
@@ -143,11 +143,11 @@ pin_project! {
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
/// sleep(Duration::from_millis(100)).await;
/// println!("100 ms have elapsed");
/// }
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// sleep(Duration::from_millis(100)).await;
/// println!("100 ms have elapsed");
/// # }
/// ```
///
/// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
@@ -155,20 +155,20 @@ pin_project! {
/// ```no_run
/// use tokio::time::{self, Duration, Instant};
///
/// #[tokio::main]
/// async fn main() {
/// let sleep = time::sleep(Duration::from_millis(10));
/// tokio::pin!(sleep);
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let sleep = time::sleep(Duration::from_millis(10));
/// tokio::pin!(sleep);
///
/// loop {
/// tokio::select! {
/// () = &mut sleep => {
/// println!("timer elapsed");
/// sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
/// },
/// }
/// loop {
/// tokio::select! {
/// () = &mut sleep => {
/// println!("timer elapsed");
/// sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
/// },
/// }
/// }
/// # }
/// ```
/// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
/// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.