mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-07 00:00:09 +02:00
ci: unfreeze wasm tests from rustc 1.88.0 (#7537)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)]
|
||||
|
||||
@@ -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;
|
||||
///
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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;
|
||||
///
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: () }
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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: () }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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")))]
|
||||
|
||||
@@ -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")))]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
+448
-442
File diff suppressed because it is too large
Load Diff
+130
-124
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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)));
|
||||
///
|
||||
|
||||
@@ -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));
|
||||
///
|
||||
|
||||
@@ -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));
|
||||
///
|
||||
|
||||
@@ -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));
|
||||
///
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
//! Tokio. For example:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[tokio::main]
|
||||
//! # #[tokio::main(flavor = "current_thread")]
|
||||
//! # async fn main() {
|
||||
//! use tokio::{task, sync::mpsc};
|
||||
//!
|
||||
|
||||
+59
-56
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user