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
- 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
- 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
/// ```
/// 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)
//! ```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
/// ```
/// 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 {
/// ```
/// 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> {
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # 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")]);
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
///
/// # Examples
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// }
/// }
///
+ /// # /*
/// #[tokio::main]
+ /// # */
+ /// # #[tokio::main(flavor = "current_thread")]
/// async fn main() {
/// let mut stream = Alternate { state: 0 };
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// # 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);
/// Basic usage:
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// Stopping at the first `false`:
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// Basic usage:
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// Stopping at the first `true`:
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as stream, StreamExt};
///
/// ```
/// 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
/// # Examples
/// Basic usage:
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{self as 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
/// ```
/// 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
/// 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;
/// 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;
/// 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);
-///
-/// // 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);
-/// }
+/// # #[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;
+/// });
///
-/// // Remove the stream to prevent reading the next value
-/// map.remove(key);
+/// 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
/// ```
/// 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)]
/// 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;
/// }
/// # Ok(())
/// # }
+/// # }
/// ```
///
/// [`TcpListener`]: struct@tokio::net::TcpListener
/// # Examples
///
/// ```
-/// # #[tokio::main]
+/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{StreamExt, wrappers::WatchStream};
/// use tokio::sync::watch;
/// ```
///
/// ```
-/// # #[tokio::main]
+/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_stream::{StreamExt, wrappers::WatchStream};
/// use tokio::sync::watch;
/// Example with [`WatchStream<T>::from_changes`]:
///
/// ```
-/// # #[tokio::main]
+/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use futures::future::FutureExt;
/// use tokio::sync::watch;
//! ```
//! # 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()
//! ```
//! # 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()
//! ```
//! # 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()
//! ```
//! # 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()
//! ```
//! # 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()
//! ```
//! # 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()
//! ```
//! # 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()
//! 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`
//! 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
//! stream via [`compat()`].
//!
//! ```no_run
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::net::{TcpListener, TcpStream};
//! use tokio::io::AsyncWriteExt;
//! use tokio_util::compat::TokioAsyncReadCompatExt;
//!
//! Ok(())
//! }
+//! # }
//! ```
//!
//! ## Example 2: Futures -> Tokio (`AsyncRead`)
//! 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;
//! // Run the future inside a Tokio runtime
//! tokio::runtime::Runtime::new().unwrap().block_on(future);
//! }
+//! # }
//! ```
//!
//! ## Common Use Cases
/// 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;
///
///
/// // Execute the future on rt2.
/// rt2.block_on(fut);
+ /// # }
/// ```
///
/// [`Handle`]: struct@tokio::runtime::Handle
/// [`RuntimeExt::wrap`]: fn@RuntimeExt::wrap
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::time::{sleep, Duration};
/// use tokio_util::context::TokioContext;
///
///
/// // Execute the future on rt2.
/// rt2.block_on(fut);
+ /// # }
/// ```
pub fn new(future: F, handle: Handle) -> TokioContext<F> {
TokioContext {
/// 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;
///
///
/// // Execute the future on rt2.
/// rt2.block_on(fut);
+ /// # }
/// ```
///
/// [`TokioContext`]: struct@crate::context::TokioContext
/// # 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)]
/// # Example
///
/// ```
-/// # #[tokio::main]
+/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> std::io::Result<()> {
/// use tokio_util::io::read_exact_arc;
///
/// 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
/// # Example
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> std::io::Result<()> {
/// use tokio_stream::StreamExt;
/// use tokio_util::io::ReaderStream;
/// 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
/// /// 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?;
/// 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
+/// # }
/// ```
///
///
/// 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;
///
/// Ok(())
/// }
+/// # }
/// ```
///
#[derive(Debug)]
/// ```
/// 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 { /* ... */ });
-/// }
+/// 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];
+/// 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);
-/// }
+/// // 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 {
+/// assert!(seen[i]);
/// }
+/// # }
/// ```
///
/// Cancel tasks based on their keys:
/// ```
/// 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
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_util::task::JoinMap;
/// use std::collections::hash_map::RandomState;
/// ```
/// use tokio_util::task::JoinMap;
///
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let mut map = JoinMap::new();
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_util::task::JoinMap;
///
/// # Examples
///
/// ```
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// use tokio_util::task::JoinMap;
///
/// # Examples
///
/// ```
+/// # #[cfg(not(target_family = "wasm"))]
+/// # {
/// use std::rc::Rc;
/// use tokio::task;
/// use tokio_util::task::LocalPoolHandle;
/// }).await.unwrap();
/// println!("output: {}", output);
/// }
+/// # }
/// ```
///
#[derive(Clone)]
///
/// # Examples
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::rc::Rc;
/// use tokio_util::task::LocalPoolHandle;
///
///
/// assert_eq!(output, "test");
/// }
+ /// # }
/// ```
pub fn spawn_pinned<F, Fut>(&self, create_task: F) -> JoinHandle<Fut::Output>
where
/// 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]
/// handle.await.unwrap();
/// }
/// }
+ /// # }
/// ```
///
#[track_caller]
/// ```
/// 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();
+/// 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;
+/// // Wait for everything to finish.
+/// tracker.wait().await;
///
-/// println!("This is printed after all of the tasks.");
-/// }
+/// println!("This is printed after all of the tasks.");
+/// # }
/// ```
///
/// ## Wait for tasks to exit
/// # 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);
///
/// 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(
/// 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));
/// 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();
///
/// 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));
/// 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));
/// 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);
///
/// 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();
///
/// 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));
/// 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();
///
/// 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);
/// 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();
///
/// 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());
/// 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
//! 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;
//!
//! println!("The bytes: {:?}", &buffer[..n]);
//! Ok(())
//! }
+//! # }
//! ```
//!
//! [`File`]: crate::fs::File
//! extra methods to any async reader:
//!
//! ```no_run
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::io::{self, BufReader, AsyncBufReadExt};
//! use tokio::fs::File;
//!
//! println!("{}", buffer);
//! Ok(())
//! }
+//! # }
//! ```
//!
//! [`BufWriter`] doesn't add any new ways of writing; it just buffers every call
//! [`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;
//!
//!
//! Ok(())
//! }
+//! # }
//! ```
//!
//! [stdbuf]: std::io#bufreader-and-bufwriter
///
/// use std::io::Cursor;
///
- /// #[tokio::main]
- /// 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");
- ///
- /// 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");
- ///
- /// 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"");
- /// }
+ /// # #[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");
+ ///
+ /// 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");
+ ///
+ /// 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"");
+ /// # }
/// ```
fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
where
///
/// 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
///
/// 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
/// [`AsyncRead`].
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
///
/// Ok(())
/// }
+ /// # }
/// ```
///
/// See [module][crate::io] documentation for more details.
/// [`File`][crate::fs::File]s implement `AsyncRead`:
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
/// handle.read_to_string(&mut buffer).await?;
/// Ok(())
/// }
+ /// # }
/// ```
fn chain<R>(self, next: R) -> Chain<Self, R>
where
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
/// println!("The bytes: {:?}", &buffer[..n]);
/// Ok(())
/// }
+ /// # }
/// ```
fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Read<'a, Self>
where
/// [`BufMut`]: bytes::BufMut
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
/// println!("The bytes: {:?}", &buffer[..]);
/// Ok(())
/// }
+ /// # }
/// ```
fn read_buf<'a, B>(&'a mut self, buf: &'a mut B) -> ReadBuf<'a, Self, B>
where
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::fs::File;
/// use tokio::io::{self, AsyncReadExt};
///
/// f.read_exact(&mut buffer).await?;
/// Ok(())
/// }
+ /// # }
/// ```
///
/// [`ErrorKind::UnexpectedEof`]: std::io::ErrorKind::UnexpectedEof
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
///
/// 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;
}
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncReadExt};
/// use tokio::fs::File;
///
/// f.read_to_end(&mut buffer).await?;
/// Ok(())
/// }
+ /// # }
/// ```
///
/// (See also the [`tokio::fs::read`] convenience function for reading from a
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncReadExt};
/// use tokio::fs::File;
///
/// f.read_to_string(&mut buffer).await?;
/// Ok(())
/// }
+ /// # }
/// ```
///
/// (See also the [`crate::fs::read_to_string`] convenience function for
/// [`File`][crate::fs::File]s implement `Read`:
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncReadExt};
/// use tokio::fs::File;
///
/// handle.read(&mut buffer).await?;
/// Ok(())
/// }
+ /// # }
/// ```
fn take(self, limit: u64) -> Take<Self>
where
/// 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.
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::fs::File;
/// use tokio::io::{AsyncSeekExt, AsyncReadExt};
///
/// file.read_exact(&mut contents).await?;
/// # Ok(())
/// # }
+ /// # }
/// ```
fn seek(&mut self, pos: SeekFrom) -> Seek<'_, Self>
where
/// [`AsyncWrite`].
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
///
/// Ok(())
/// }
+ /// # }
/// ```
///
/// See [module][crate::io] documentation for more details.
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
/// file.flush().await?;
/// Ok(())
/// }
+ /// # }
/// ```
fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
/// use std::io::IoSlice;
///
/// Ok(())
/// }
+ /// # }
/// ```
///
/// [`write`]: AsyncWriteExt::write
/// [`Cursor`]: std::io::Cursor
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
///
/// Ok(())
/// }
+ /// # }
/// ```
fn write_buf<'a, B>(&'a mut self, src: &'a mut B) -> WriteBuf<'a, Self, B>
where
/// [advanced]: bytes::Buf::advance
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
/// file.flush().await?;
/// Ok(())
/// }
+ /// # }
/// ```
///
/// [`write`]: AsyncWriteExt::write
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, AsyncWriteExt};
/// use tokio::fs::File;
///
/// file.flush().await?;
/// Ok(())
/// }
+ /// # }
/// ```
///
/// [`write`]: AsyncWriteExt::write
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
/// ```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;
}
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, BufWriter, AsyncWriteExt};
/// use tokio::fs::File;
///
/// buffer.flush().await?;
/// Ok(())
/// }
+ /// # }
/// ```
fn flush(&mut self) -> Flush<'_, Self>
where
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::io::{self, BufWriter, AsyncWriteExt};
/// use tokio::fs::File;
///
/// buffer.shutdown().await?;
/// Ok(())
/// }
+ /// # }
/// ```
fn shutdown(&mut self) -> Shutdown<'_, Self>
where
/// ```
/// 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:
/// ```
/// 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: () }
/// ```
/// 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 }
/// ```
/// 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: () }
//! [`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.
//! // panic.
//! blocking_task.await.unwrap();
//! }
+//! # }
//! ```
//!
//! If your code is CPU-bound and you wish to limit the number of threads used
//! A simple TCP echo server:
//!
//! ```no_run
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::net::TcpListener;
//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
//!
//! });
//! }
//! }
+//! # }
//! ```
//!
//! # Feature flags
/// # Examples
///
/// ```
+/// # #[cfg(not(target_family = "wasm"))]
+/// # {
/// use std::sync::{Arc, Barrier};
/// use std::thread;
///
/// for handle in handles {
/// handle.join().unwrap();
/// }
+/// # }
/// ```
pub(crate) struct Barrier {
lock: Mutex<BarrierState>,
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::sync::{Arc, Barrier};
/// use std::thread;
///
/// for handle in handles {
/// handle.join().unwrap();
/// }
+ /// # }
/// ```
pub(crate) fn wait(&self) -> BarrierWaitResult {
let mut lock = self.lock.lock();
/// // 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
/// }
/// // 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]
/// // 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:
/// // async logic here
/// }
///
-/// #[tokio::main]
-/// async fn main() {
-/// let mut stream = stream::iter(vec![1, 2, 3, 4]);
-///
-/// 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);
-/// }
+/// # #[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);
+///
+/// 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
/// // async logic here
/// }
///
-/// #[tokio::main]
-/// async fn main() {
-/// pin! {
-/// let future1 = my_async_fn();
-/// let future2 = my_async_fn();
-/// }
+/// # #[tokio::main(flavor = "current_thread")]
+/// # async fn main() {
+/// pin! {
+/// let future1 = my_async_fn();
+/// let future2 = my_async_fn();
+/// }
///
-/// select! {
-/// _ = &mut future1 => {}
-/// _ = &mut future2 => {}
-/// }
+/// select! {
+/// _ = &mut future1 => {}
+/// _ = &mut future2 => {}
/// }
+/// # }
/// ```
#[macro_export]
macro_rules! pin {
/// // 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.
/// ```
/// 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
/// ```
/// 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
/// 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);
- ///
- /// loop {
- /// tokio::select! {
- /// maybe_v = stream.next() => {
- /// if let Some(v) = maybe_v {
- /// println!("got = {}", v);
- /// } else {
- /// break;
- /// }
- /// }
- /// _ = &mut sleep => {
- /// println!("timeout");
+ /// # #[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");
+ /// break;
+ /// }
/// }
/// }
+ /// # }
/// ```
///
/// Joining two values using `select!`.
/// ```
/// 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());
+ /// let res = (a.unwrap(), b.unwrap());
///
- /// assert_eq!(res.0, "first");
- /// assert_eq!(res.1, "second");
- /// }
+ /// 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;
- ///
- /// 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);
- /// }
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let mut count = 0u8;
///
- /// else => {
- /// break;
- /// }
- /// };
- /// }
+ /// 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);
+ /// }
+ ///
+ /// else => {
+ /// break;
+ /// }
+ /// };
/// }
+ /// # }
/// ```
///
/// ## Avoid racy `if` preconditions
/// // 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
/// // 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
///
/// // 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;
- ///
- /// loop {
- /// tokio::select! {
- /// _ = read_send(&mut file, &mut channel) => { /* ... */ },
- /// _data = socket.read_packet() => { /* ... */ }
- /// _ = futures::future::ready(()) => break
- /// }
+ /// # #[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
/// }
/// }
- ///
+ /// # }
/// ```
///
/// ### Moving to `merge`
/// Data(Vec<u8>),
/// }
///
- /// #[tokio::main]
- /// 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 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,
- /// }
+ /// # #[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 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
/// ```
/// 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")))]
/// # 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.
/// }
/// }
///
- /// #[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.
///
/// # 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")))]
/// # Examples
///
/// ```
+/// # #[cfg(not(target_family = "wasm"))]
+/// # {
/// use tokio::runtime::Builder;
///
/// fn main() {
///
/// // use runtime ...
/// }
+/// # }
/// ```
pub struct Builder {
/// Runtime type
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::{self, UnhandledPanic};
///
/// # pub fn main() {
/// assert!(task2.await.is_ok());
/// })
/// # }
+ /// # }
/// ```
///
/// [`JoinHandle`]: struct@crate::task::JoinHandle
/// # 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(
/// ## 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.
/// .unwrap();
///
/// rt.spawn(async move {});
+ /// # }
/// ```
///
/// ## Current thread runtime (will only run on the current thread via `Runtime::block_on`)
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use tokio::runtime;
///
/// # pub fn main() {
/// .thread_name("my-pool")
/// .build();
/// # }
+ /// # }
/// ```
pub fn thread_name(&mut self, val: impl Into<String>) -> &mut Self {
let val = val.into();
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use tokio::runtime;
/// # use std::sync::atomic::{AtomicUsize, Ordering};
/// # pub fn main() {
/// })
/// .build();
/// # }
+ /// # }
/// ```
pub fn thread_name_fn<F>(&mut self, f: F) -> &mut Self
where
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use tokio::runtime;
///
/// # pub fn main() {
/// .thread_stack_size(32 * 1024)
/// .build();
/// # }
+ /// # }
/// ```
pub fn thread_stack_size(&mut self, val: usize) -> &mut Self {
self.thread_stack_size = Some(val);
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use tokio::runtime;
/// # pub fn main() {
/// let runtime = runtime::Builder::new_multi_thread()
/// })
/// .build();
/// # }
+ /// # }
/// ```
#[cfg(not(loom))]
pub fn on_thread_start<F>(&mut self, f: F) -> &mut Self
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// {
/// # use tokio::runtime;
/// # pub fn main() {
/// let runtime = runtime::Builder::new_multi_thread()
/// })
/// .build();
/// # }
+ /// # }
/// ```
#[cfg(not(loom))]
pub fn on_thread_stop<F>(&mut self, f: F) -> &mut Self
///
/// ## Multithreaded executor
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use std::sync::Arc;
/// # use std::sync::atomic::{AtomicBool, Ordering};
/// # use tokio::runtime;
/// barrier.wait().await;
/// })
/// # }
+ /// # }
/// ```
/// ## Current thread executor
/// ```
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use tokio::runtime;
/// # pub fn main() {
/// let runtime = runtime::Builder::new_multi_thread()
/// println!("Hello from Tokio!");
/// })
/// # }
+ /// # }
/// ```
#[cfg(not(loom))]
pub fn on_thread_unpark<F>(&mut self, f: F) -> &mut Self
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use std::sync::{atomic::AtomicUsize, Arc};
/// # use tokio::task::yield_now;
/// # pub fn main() {
/// let _ = rt.block_on(task);
///
/// # }
+ /// # }
/// ```
#[cfg(tokio_unstable)]
#[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use std::sync::{atomic::AtomicUsize, Arc};
/// # use tokio::task::yield_now;
/// # pub fn main() {
/// let _ = rt.block_on(task);
///
/// # }
+ /// # }
/// ```
#[cfg(tokio_unstable)]
#[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Builder;
///
/// let rt = Builder::new_multi_thread().build().unwrap();
/// rt.block_on(async {
/// println!("Hello from the Tokio runtime");
/// });
+ /// # }
/// ```
pub fn build(&mut self) -> io::Result<Runtime> {
match &self.kind {
/// # Example
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use tokio::runtime;
/// # use std::time::Duration;
/// # pub fn main() {
/// .thread_keep_alive(Duration::from_millis(100))
/// .build();
/// # }
+ /// # }
/// ```
pub fn thread_keep_alive(&mut self, duration: Duration) -> &mut Self {
self.keep_alive = Some(duration);
/// # 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 {
/// # 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;
/// # 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
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime;
///
/// let rt = runtime::Builder::new_multi_thread()
/// # 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
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::{self, HistogramScale};
///
/// # #[allow(deprecated)]
/// .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 {
/// # Examples
/// Configure a [`LogHistogram`] with [default configuration]:
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime;
/// use tokio::runtime::{HistogramConfiguration, LogHistogram};
///
/// )
/// .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;
/// )
/// .build()
/// .unwrap();
+ /// # }
/// ```
///
/// Configure a [`LogHistogram`] with the following settings:
/// - 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};
/// )
/// .build()
/// .unwrap();
+ /// # }
/// ```
///
/// When migrating from the legacy histogram ([`HistogramScale::Log`]) and wanting
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime;
/// use std::time::Duration;
///
/// .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 {
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime;
///
/// # #[allow(deprecated)]
/// .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 {
/// # 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;
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// let rt = Runtime::new().unwrap();
/// 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();
/// block or function running on that runtime.
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// # use std::thread;
/// # use tokio::runtime::Runtime;
/// # fn dox() {
/// # handle.join().unwrap();
/// # });
/// # }
+ /// # }
/// ```
#[track_caller]
pub fn current() -> Self {
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
/// println!("now running on a worker thread");
/// });
/// # }
+ /// # }
/// ```
#[track_caller]
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
/// println!("now running on a worker thread");
/// });
/// # }
+ /// # }
+ /// ```
#[track_caller]
pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
where
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// // Create the runtime
/// handle.block_on(async {
/// println!("hello");
/// });
+ /// # }
/// ```
///
/// Or using `Handle::current`:
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// });
/// });
/// }
+ /// # }
/// ```
///
/// [`JoinError`]: struct@crate::task::JoinError
/// ```
///
/// ```
+ /// # #[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 {
/// # 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
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::LocalRuntime;
/// use tokio::task;
///
///
/// runtime.shutdown_timeout(Duration::from_millis(100));
/// }
+ /// # }
/// ```
pub fn shutdown_timeout(mut self, duration: Duration) {
// Wakeup and shutdown all the worker threads
/// ```
/// 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()
/// ```
/// 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()
/// ```
/// 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()
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// # 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();
- ///
- /// let n = metrics.num_blocking_threads();
- /// println!("Runtime has created {} threads", n);
- /// }
+ /// # #[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);
+ /// # }
+ /// # }
/// ```
pub fn num_blocking_threads(&self) -> usize {
self.handle.inner.num_blocking_threads()
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Handle;
///
/// #[tokio::main]
/// 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()
/// ```
/// 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
/// ```
/// 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)
/// ```
/// 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()
/// ```
/// 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()
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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 {
//! used.
//!
//! ```no_run
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::net::TcpListener;
//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
//!
//! });
//! }
//! }
+//! # }
//! ```
//!
//! From within the context of the runtime, additional tasks are spawned using
//! 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;
//! }
//! })
//! }
+//! # }
//! ```
//!
//! ## Runtime Configurations
//! 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
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// let rt = Runtime::new()
/// let handle = rt.handle();
///
/// // Use the handle...
+ /// # }
/// ```
pub fn handle(&self) -> &Handle {
&self.handle
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
/// println!("now running on a worker thread");
/// });
/// # }
+ /// # }
/// ```
#[track_caller]
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// # fn dox() {
/// println!("now running on a worker thread");
/// });
/// # }
+ /// # }
/// ```
#[track_caller]
pub fn spawn_blocking<F, R>(&self, func: F) -> JoinHandle<R>
/// # Examples
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// // Create the runtime
/// rt.block_on(async {
/// println!("hello");
/// });
+ /// # }
/// ```
///
/// [handle]: fn@Handle::block_on
/// # Example
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
/// use tokio::task::JoinHandle;
///
/// // Wait for the task before we end the test.
/// rt.block_on(handle).unwrap();
/// }
+ /// # }
/// ```
pub fn enter(&self) -> EnterGuard<'_> {
self.handle.enter()
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
/// use tokio::task;
///
///
/// runtime.shutdown_timeout(Duration::from_millis(100));
/// }
+ /// # }
/// ```
pub fn shutdown_timeout(mut self, duration: Duration) {
// Wakeup and shutdown all the worker threads
/// This function is equivalent to calling `shutdown_timeout(Duration::from_nanos(0))`.
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
///
/// fn main() {
/// inner_runtime.shutdown_background();
/// });
/// }
+ /// # }
/// ```
pub fn shutdown_background(self) {
self.shutdown_timeout(Duration::from_nanos(0));
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::panic;
///
/// #[tokio::main]
///
/// assert!(err.is_panic());
/// }
+ /// # }
/// ```
pub fn is_panic(&self) -> bool {
matches!(&self.repr, Repr::Panic(_))
///
/// # Examples
///
- /// ```should_panic
+ /// ```should_panic,ignore-wasm
/// use std::panic;
///
/// #[tokio::main]
///
/// # Examples
///
- /// ```should_panic
+ /// ```should_panic,ignore-wasm
/// use std::panic;
///
/// #[tokio::main]
/// 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;
/// assert!(err.is_panic());
/// Ok(())
/// }
- ///
+ /// # }
/// ```
/// Child being detached and outliving its parent:
///
/// 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.
/// 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;
//! ```
//! 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
//! ```
//! 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;
/// ```
/// 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
/// ```
/// 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>>,
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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();
/// ```
/// 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();
/// ```
/// 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();
/// ```
/// 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();
/// ```
/// 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();
/// ```
/// 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)
/// 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 {
/// ```
/// 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;
/// ```
/// 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
/// ```
/// 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)
/// ```
/// 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
/// ```
/// 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();
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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)?;
///
/// # Examples
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::thread;
/// use tokio::sync::broadcast;
///
/// let _ = tx.send(10);
/// sync_code.join().unwrap();
/// }
+ /// # }
/// ```
pub fn blocking_recv(&mut self) -> Result<T, RecvError> {
crate::future::block_on(self.recv())
//! "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
//! "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
//! format!("the result of computation {}", input)
//! }
//!
-//! #[tokio::main]
-//! 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();
-//! }
-//! });
+//! # #[tokio::main(flavor = "current_thread")]
+//! # async fn main() {
+//! let (tx, mut rx) = mpsc::channel(100);
//!
-//! 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
//! passing.
//!
//! ```no_run
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::io::{self, AsyncWriteExt};
//! use tokio::net::TcpStream;
//! use tokio::sync::mpsc;
//!
//! Ok(())
//! }
+//! # }
//! ```
//!
//! The [`mpsc`] and [`oneshot`] channels can be combined to provide a request /
//! // Other commands can be added here
//! }
//!
-//! #[tokio::main]
-//! 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;
-//!
-//! while let Some((cmd, response)) = cmd_rx.recv().await {
-//! match cmd {
-//! Increment => {
-//! let prev = counter;
-//! counter += 1;
-//! response.send(prev).unwrap();
-//! }
+//! # #[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;
+//!
+//! 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![];
+//! let mut join_handles = vec![];
//!
-//! // Spawn tasks that will send the increment command.
-//! for _ in 0..10 {
-//! let cmd_tx = cmd_tx.clone();
+//! // 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();
+//! 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();
+//! cmd_tx.send((Increment, resp_tx)).await.ok().unwrap();
+//! let res = resp_rx.await.unwrap();
//!
-//! println!("previous value = {}", res);
-//! }));
-//! }
+//! println!("previous value = {}", res);
+//! }));
+//! }
//!
-//! // Wait for all tasks to complete
-//! for join_handle in join_handles.drain(..) {
-//! join_handle.await.unwrap();
-//! }
+//! // Wait for all tasks to complete
+//! for join_handle in join_handles.drain(..) {
+//! join_handle.await.unwrap();
//! }
+//! # }
//! ```
//!
//! ## `broadcast` channel
//! ```
//! 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
//! // 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;
+//! // 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();
+//! // 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;
-//! }
+//! // 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);
+//!
+//! 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();
//!
-//! 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
-//! }
+//! // 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);
-//! }
+//! handles.push(handle);
+//! }
//!
-//! for handle in handles.drain(..) {
-//! handle.await.unwrap();
-//! }
+//! for handle in handles.drain(..) {
+//! handle.await.unwrap();
//! }
+//! # }
//! ```
//!
//! [`watch` channel]: mod@crate::sync::watch
/// ```
/// use tokio::sync::mpsc::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> {
chan: Arc<chan::Chan<T, Semaphore>>,
/// ```rust
/// use tokio::sync::mpsc;
///
-/// #[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 {
-/// if let Err(_) = tx.send(i).await {
-/// println!("receiver dropped");
-/// return;
-/// }
+/// tokio::spawn(async move {
+/// for i in 0..10 {
+/// if let Err(_) = tx.send(i).await {
+/// println!("receiver dropped");
+/// return;
/// }
-/// });
-///
-/// while let Some(i) = rx.recv().await {
-/// println!("got = {}", i);
/// }
+/// });
+///
+/// while let Some(i) = rx.recv().await {
+/// println!("got = {}", i);
/// }
+/// # }
/// ```
#[track_caller]
pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[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 {
- /// tx.send("hello").await.unwrap();
- /// });
+ /// tokio::spawn(async move {
+ /// tx.send("hello").await.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:
/// ```
/// use tokio::sync::mpsc;
///
- /// #[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);
///
- /// tx.send("hello").await.unwrap();
- /// tx.send("world").await.unwrap();
+ /// tx.send("hello").await.unwrap();
+ /// tx.send("world").await.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;
/// ```
/// 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::channel(100);
- /// let tx2 = tx.clone();
- /// tx2.send("first").await.unwrap();
- /// tx2.send("second").await.unwrap();
- /// tx2.send("third").await.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);
- ///
- /// // If the buffer is full, the next call to `recv_many`
- /// // reserves additional capacity.
- /// assert_eq!(1, rx.recv_many(&mut buffer, 1).await);
- ///
- /// tokio::spawn(async move {
- /// tx.send("fourth").await.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, 1).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);
- /// }
+ /// # #[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::channel(100);
+ /// let tx2 = tx.clone();
+ /// tx2.send("first").await.unwrap();
+ /// tx2.send("second").await.unwrap();
+ /// tx2.send("third").await.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);
+ ///
+ /// // If the buffer is full, the next call to `recv_many`
+ /// // reserves additional capacity.
+ /// assert_eq!(1, rx.recv_many(&mut buffer, 1).await);
+ ///
+ /// tokio::spawn(async move {
+ /// tx.send("fourth").await.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, 1).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;
/// use tokio::sync::mpsc;
/// use tokio::sync::mpsc::error::TryRecvError;
///
- /// #[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);
///
- /// tx.send("hello").await.unwrap();
+ /// tx.send("hello").await.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").await.unwrap();
- /// // Drop the last sender, closing the channel.
- /// drop(tx);
+ /// tx.send("hello").await.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()
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::thread;
/// use tokio::runtime::Runtime;
/// use tokio::sync::mpsc;
/// });
/// sync_code.join().unwrap()
/// }
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(20);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(20);
///
- /// tokio::spawn(async move {
- /// let mut i = 0;
- /// while let Ok(permit) = tx.reserve().await {
- /// permit.send(i);
- /// i += 1;
- /// }
- /// });
- ///
- /// rx.close();
- ///
- /// while let Some(msg) = rx.recv().await {
- /// println!("got {}", msg);
+ /// tokio::spawn(async move {
+ /// let mut i = 0;
+ /// while let Ok(permit) = tx.reserve().await {
+ /// permit.send(i);
+ /// i += 1;
/// }
+ /// });
///
- /// // Channel closed and no messages are lost.
+ /// rx.close();
+ ///
+ /// while let Some(msg) = rx.recv().await {
+ /// println!("got {}", msg);
/// }
+ ///
+ /// // Channel closed and no messages are lost.
+ /// # }
/// ```
pub fn close(&mut self) {
self.chan.close();
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (_tx, mut rx) = mpsc::channel::<()>(10);
- /// assert!(!rx.is_closed());
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (_tx, mut rx) = mpsc::channel::<()>(10);
+ /// 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()
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel(10);
- /// assert!(rx.is_empty());
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel(10);
+ /// assert!(rx.is_empty());
///
- /// tx.send(0).await.unwrap();
- /// assert!(!rx.is_empty());
- /// }
+ /// tx.send(0).await.unwrap();
+ /// assert!(!rx.is_empty());
+ /// # }
///
/// ```
pub fn is_empty(&self) -> bool {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel(10);
- /// assert_eq!(0, rx.len());
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel(10);
+ /// assert_eq!(0, rx.len());
///
- /// tx.send(0).await.unwrap();
- /// assert_eq!(1, rx.len());
- /// }
+ /// tx.send(0).await.unwrap();
+ /// assert_eq!(1, rx.len());
+ /// # }
/// ```
pub fn len(&self) -> usize {
self.chan.len()
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel::<()>(5);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel::<()>(5);
///
- /// assert_eq!(rx.capacity(), 5);
+ /// assert_eq!(rx.capacity(), 5);
///
- /// // Making a reservation drops the capacity by one.
- /// let permit = tx.reserve().await.unwrap();
- /// assert_eq!(rx.capacity(), 4);
- /// assert_eq!(rx.len(), 0);
+ /// // Making a reservation drops the capacity by one.
+ /// let permit = tx.reserve().await.unwrap();
+ /// assert_eq!(rx.capacity(), 4);
+ /// assert_eq!(rx.len(), 0);
///
- /// // Sending and receiving a value increases the capacity by one.
- /// permit.send(());
- /// assert_eq!(rx.len(), 1);
- /// rx.recv().await.unwrap();
- /// assert_eq!(rx.capacity(), 5);
+ /// // Sending and receiving a value increases the capacity by one.
+ /// permit.send(());
+ /// assert_eq!(rx.len(), 1);
+ /// rx.recv().await.unwrap();
+ /// assert_eq!(rx.capacity(), 5);
///
- /// // Directly sending a message drops the capacity by one.
- /// tx.send(()).await.unwrap();
- /// assert_eq!(rx.capacity(), 4);
- /// assert_eq!(rx.len(), 1);
+ /// // Directly sending a message drops the capacity by one.
+ /// tx.send(()).await.unwrap();
+ /// assert_eq!(rx.capacity(), 4);
+ /// assert_eq!(rx.len(), 1);
///
- /// // Receiving the message increases the capacity by one.
- /// rx.recv().await.unwrap();
- /// assert_eq!(rx.capacity(), 5);
- /// assert_eq!(rx.len(), 0);
- /// }
+ /// // Receiving the message increases the capacity by one.
+ /// rx.recv().await.unwrap();
+ /// assert_eq!(rx.capacity(), 5);
+ /// assert_eq!(rx.len(), 0);
+ /// # }
/// ```
/// [`capacity`]: Receiver::capacity
/// [`max_capacity`]: Receiver::max_capacity
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel::<()>(5);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel::<()>(5);
///
- /// // both max capacity and capacity are the same at first
- /// assert_eq!(rx.max_capacity(), 5);
- /// assert_eq!(rx.capacity(), 5);
+ /// // both max capacity and capacity are the same at first
+ /// assert_eq!(rx.max_capacity(), 5);
+ /// assert_eq!(rx.capacity(), 5);
///
- /// // Making a reservation doesn't change the max capacity.
- /// let permit = tx.reserve().await.unwrap();
- /// assert_eq!(rx.max_capacity(), 5);
- /// // but drops the capacity by one
- /// assert_eq!(rx.capacity(), 4);
- /// }
+ /// // Making a reservation doesn't change the max capacity.
+ /// let permit = tx.reserve().await.unwrap();
+ /// assert_eq!(rx.max_capacity(), 5);
+ /// // but drops the capacity by one
+ /// assert_eq!(rx.capacity(), 4);
+ /// # }
/// ```
/// [`capacity`]: Receiver::capacity
/// [`max_capacity`]: Receiver::max_capacity
/// }
/// }
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel(32);
- /// let mut buffer = Vec::new();
- ///
- /// let my_receiver_future = MyReceiverFuture {
- /// receiver: rx,
- /// buffer: &mut buffer,
- /// limit: 3,
- /// };
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel(32);
+ /// let mut buffer = Vec::new();
///
- /// for i in 0..10 {
- /// tx.send(i).await.unwrap();
- /// }
+ /// let my_receiver_future = MyReceiverFuture {
+ /// receiver: rx,
+ /// buffer: &mut buffer,
+ /// limit: 3,
+ /// };
///
- /// 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).await.unwrap();
/// }
+ ///
+ /// let count = my_receiver_future.await;
+ /// assert_eq!(count, 3);
+ /// assert_eq!(buffer, vec![0,1,2])
+ /// # }
/// ```
pub fn poll_recv_many(
&mut self,
/// ```rust
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// tokio::spawn(async move {
- /// for i in 0..10 {
- /// if let Err(_) = tx.send(i).await {
- /// println!("receiver dropped");
- /// return;
- /// }
+ /// tokio::spawn(async move {
+ /// for i in 0..10 {
+ /// if let Err(_) = tx.send(i).await {
+ /// println!("receiver dropped");
+ /// return;
/// }
- /// });
- ///
- /// while let Some(i) = rx.recv().await {
- /// println!("got = {}", i);
/// }
+ /// });
+ ///
+ /// while let Some(i) = rx.recv().await {
+ /// println!("got = {}", i);
/// }
+ /// # }
/// ```
pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
match self.reserve().await {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx1, rx) = mpsc::channel::<()>(1);
- /// 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");
- /// }
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx1, rx) = mpsc::channel::<()>(1);
+ /// 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");
+ /// # }
/// ```
pub async fn closed(&self) {
self.chan.closed().await;
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// // Create a channel with buffer size 1
- /// let (tx1, mut rx) = mpsc::channel(1);
- /// let tx2 = tx1.clone();
- ///
- /// tokio::spawn(async move {
- /// tx1.send(1).await.unwrap();
- /// tx1.send(2).await.unwrap();
- /// // task waits until the receiver receives a value.
- /// });
- ///
- /// tokio::spawn(async move {
- /// // This will return an error and send
- /// // no message if the buffer is full
- /// let _ = tx2.try_send(3);
- /// });
- ///
- /// let mut msg;
- /// msg = rx.recv().await.unwrap();
- /// println!("message {} received", msg);
- ///
- /// msg = rx.recv().await.unwrap();
- /// println!("message {} received", msg);
- ///
- /// // Third message may have never been sent
- /// match rx.recv().await {
- /// Some(msg) => println!("message {} received", msg),
- /// None => println!("the third message was never sent"),
- /// }
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// // Create a channel with buffer size 1
+ /// let (tx1, mut rx) = mpsc::channel(1);
+ /// let tx2 = tx1.clone();
+ ///
+ /// tokio::spawn(async move {
+ /// tx1.send(1).await.unwrap();
+ /// tx1.send(2).await.unwrap();
+ /// // task waits until the receiver receives a value.
+ /// });
+ ///
+ /// tokio::spawn(async move {
+ /// // This will return an error and send
+ /// // no message if the buffer is full
+ /// let _ = tx2.try_send(3);
+ /// });
+ ///
+ /// let mut msg;
+ /// msg = rx.recv().await.unwrap();
+ /// println!("message {} received", msg);
+ ///
+ /// msg = rx.recv().await.unwrap();
+ /// println!("message {} received", msg);
+ ///
+ /// // Third message may have never been sent
+ /// match rx.recv().await {
+ /// Some(msg) => println!("message {} received", msg),
+ /// None => println!("the third message was never sent"),
/// }
+ /// # }
/// ```
pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
match self.chan.semaphore().semaphore.try_acquire(1) {
/// use tokio::sync::mpsc;
/// use tokio::time::{sleep, Duration};
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// tokio::spawn(async move {
- /// for i in 0..10 {
- /// if let Err(e) = tx.send_timeout(i, Duration::from_millis(100)).await {
- /// println!("send error: #{:?}", e);
- /// return;
- /// }
+ /// tokio::spawn(async move {
+ /// for i in 0..10 {
+ /// if let Err(e) = tx.send_timeout(i, Duration::from_millis(100)).await {
+ /// println!("send error: #{:?}", e);
+ /// return;
/// }
- /// });
- ///
- /// while let Some(i) = rx.recv().await {
- /// println!("got = {}", i);
- /// sleep(Duration::from_millis(200)).await;
/// }
+ /// });
+ ///
+ /// while let Some(i) = rx.recv().await {
+ /// println!("got = {}", i);
+ /// sleep(Duration::from_millis(200)).await;
/// }
+ /// # }
/// ```
#[cfg(feature = "time")]
#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::thread;
/// use tokio::runtime::Runtime;
/// use tokio::sync::mpsc;
/// });
/// sync_code.join().unwrap()
/// }
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Reserve capacity
- /// let permit = tx.reserve().await.unwrap();
+ /// // Reserve capacity
+ /// let permit = tx.reserve().await.unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Sending on the permit succeeds
- /// permit.send(456);
+ /// // Sending on the permit succeeds
+ /// permit.send(456);
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
- /// }
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// # }
/// ```
pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
self.reserve_inner(1).await?;
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(2);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(2);
///
- /// // Reserve capacity
- /// let mut permit = tx.reserve_many(2).await.unwrap();
+ /// // Reserve capacity
+ /// let mut permit = tx.reserve_many(2).await.unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Sending with the permit iterator succeeds
- /// permit.next().unwrap().send(456);
- /// permit.next().unwrap().send(457);
+ /// // Sending with the permit iterator succeeds
+ /// permit.next().unwrap().send(456);
+ /// permit.next().unwrap().send(457);
///
- /// // The iterator should now be exhausted
- /// assert!(permit.next().is_none());
+ /// // The iterator should now be exhausted
+ /// assert!(permit.next().is_none());
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
- /// assert_eq!(rx.recv().await.unwrap(), 457);
- /// }
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// assert_eq!(rx.recv().await.unwrap(), 457);
+ /// # }
/// ```
pub async fn reserve_many(&self, n: usize) -> Result<PermitIterator<'_, T>, SendError<()>> {
self.reserve_inner(n).await?;
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Reserve capacity, moving the sender.
- /// let permit = tx.reserve_owned().await.unwrap();
+ /// // Reserve capacity, moving the sender.
+ /// let permit = tx.reserve_owned().await.unwrap();
///
- /// // Send a message, consuming the permit and returning
- /// // the moved sender.
- /// let tx = permit.send(123);
+ /// // Send a message, consuming the permit and returning
+ /// // the moved sender.
+ /// let tx = permit.send(123);
///
- /// // The value sent on the permit is received.
- /// assert_eq!(rx.recv().await.unwrap(), 123);
+ /// // The value sent on the permit is received.
+ /// assert_eq!(rx.recv().await.unwrap(), 123);
///
- /// // The sender can now be used again.
- /// tx.send(456).await.unwrap();
- /// }
+ /// // The sender can now be used again.
+ /// tx.send(456).await.unwrap();
+ /// # }
/// ```
///
/// When multiple [`OwnedPermit`]s are needed, or the sender cannot be moved
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Clone the sender and reserve capacity.
- /// let permit = tx.clone().reserve_owned().await.unwrap();
+ /// // Clone the sender and reserve capacity.
+ /// let permit = tx.clone().reserve_owned().await.unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Sending on the permit succeeds.
- /// permit.send(456);
+ /// // Sending on the permit succeeds.
+ /// permit.send(456);
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
- /// }
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// # }
/// ```
///
/// [`Sender::reserve`]: Sender::reserve
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Reserve capacity
- /// let permit = tx.try_reserve().unwrap();
+ /// // Reserve capacity
+ /// let permit = tx.try_reserve().unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Trying to reserve an additional slot on the `tx` will
- /// // fail because there is no capacity.
- /// assert!(tx.try_reserve().is_err());
+ /// // Trying to reserve an additional slot on the `tx` will
+ /// // fail because there is no capacity.
+ /// assert!(tx.try_reserve().is_err());
///
- /// // Sending on the permit succeeds
- /// permit.send(456);
+ /// // Sending on the permit succeeds
+ /// permit.send(456);
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
///
- /// }
+ /// # }
/// ```
pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
match self.chan.semaphore().semaphore.try_acquire(1) {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(2);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(2);
///
- /// // Reserve capacity
- /// let mut permit = tx.try_reserve_many(2).unwrap();
+ /// // Reserve capacity
+ /// let mut permit = tx.try_reserve_many(2).unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Trying to reserve an additional slot on the `tx` will
- /// // fail because there is no capacity.
- /// assert!(tx.try_reserve().is_err());
+ /// // Trying to reserve an additional slot on the `tx` will
+ /// // fail because there is no capacity.
+ /// assert!(tx.try_reserve().is_err());
///
- /// // Sending with the permit iterator succeeds
- /// permit.next().unwrap().send(456);
- /// permit.next().unwrap().send(457);
+ /// // Sending with the permit iterator succeeds
+ /// permit.next().unwrap().send(456);
+ /// permit.next().unwrap().send(457);
///
- /// // The iterator should now be exhausted
- /// assert!(permit.next().is_none());
+ /// // The iterator should now be exhausted
+ /// assert!(permit.next().is_none());
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
- /// assert_eq!(rx.recv().await.unwrap(), 457);
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// assert_eq!(rx.recv().await.unwrap(), 457);
///
- /// // Trying to call try_reserve_many with 0 will return an empty iterator
- /// let mut permit = tx.try_reserve_many(0).unwrap();
- /// assert!(permit.next().is_none());
+ /// // Trying to call try_reserve_many with 0 will return an empty iterator
+ /// let mut permit = tx.try_reserve_many(0).unwrap();
+ /// assert!(permit.next().is_none());
///
- /// // Trying to call try_reserve_many with a number greater than the channel
- /// // capacity will return an error
- /// let permit = tx.try_reserve_many(3);
- /// assert!(permit.is_err());
+ /// // Trying to call try_reserve_many with a number greater than the channel
+ /// // capacity will return an error
+ /// let permit = tx.try_reserve_many(3);
+ /// assert!(permit.is_err());
///
- /// // Trying to call try_reserve_many on a closed channel will return an error
- /// drop(rx);
- /// let permit = tx.try_reserve_many(1);
- /// assert!(permit.is_err());
+ /// // Trying to call try_reserve_many on a closed channel will return an error
+ /// drop(rx);
+ /// let permit = tx.try_reserve_many(1);
+ /// assert!(permit.is_err());
///
- /// let permit = tx.try_reserve_many(0);
- /// assert!(permit.is_err());
- /// }
+ /// let permit = tx.try_reserve_many(0);
+ /// assert!(permit.is_err());
+ /// # }
/// ```
pub fn try_reserve_many(&self, n: usize) -> Result<PermitIterator<'_, T>, TrySendError<()>> {
if n > self.max_capacity() {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Reserve capacity
- /// let permit = tx.clone().try_reserve_owned().unwrap();
+ /// // Reserve capacity
+ /// let permit = tx.clone().try_reserve_owned().unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Trying to reserve an additional slot on the `tx` will
- /// // fail because there is no capacity.
- /// assert!(tx.try_reserve().is_err());
+ /// // Trying to reserve an additional slot on the `tx` will
+ /// // fail because there is no capacity.
+ /// assert!(tx.try_reserve().is_err());
///
- /// // Sending on the permit succeeds
- /// permit.send(456);
+ /// // Sending on the permit succeeds
+ /// permit.send(456);
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
///
- /// }
+ /// # }
/// ```
pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
match self.chan.semaphore().semaphore.try_acquire(1) {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel::<()>(5);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel::<()>(5);
///
- /// assert_eq!(tx.capacity(), 5);
+ /// assert_eq!(tx.capacity(), 5);
///
- /// // Making a reservation drops the capacity by one.
- /// let permit = tx.reserve().await.unwrap();
- /// assert_eq!(tx.capacity(), 4);
+ /// // Making a reservation drops the capacity by one.
+ /// let permit = tx.reserve().await.unwrap();
+ /// assert_eq!(tx.capacity(), 4);
///
- /// // Sending and receiving a value increases the capacity by one.
- /// permit.send(());
- /// rx.recv().await.unwrap();
- /// assert_eq!(tx.capacity(), 5);
- /// }
+ /// // Sending and receiving a value increases the capacity by one.
+ /// permit.send(());
+ /// rx.recv().await.unwrap();
+ /// assert_eq!(tx.capacity(), 5);
+ /// # }
/// ```
///
/// [`send`]: Sender::send
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, _rx) = mpsc::channel::<()>(5);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, _rx) = mpsc::channel::<()>(5);
///
- /// // both max capacity and capacity are the same at first
- /// assert_eq!(tx.max_capacity(), 5);
- /// assert_eq!(tx.capacity(), 5);
+ /// // both max capacity and capacity are the same at first
+ /// assert_eq!(tx.max_capacity(), 5);
+ /// assert_eq!(tx.capacity(), 5);
///
- /// // Making a reservation doesn't change the max capacity.
- /// let permit = tx.reserve().await.unwrap();
- /// assert_eq!(tx.max_capacity(), 5);
- /// // but drops the capacity by one
- /// assert_eq!(tx.capacity(), 4);
- /// }
+ /// // Making a reservation doesn't change the max capacity.
+ /// let permit = tx.reserve().await.unwrap();
+ /// assert_eq!(tx.max_capacity(), 5);
+ /// // but drops the capacity by one
+ /// assert_eq!(tx.capacity(), 4);
+ /// # }
/// ```
///
/// [`channel`]: channel
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Reserve capacity
- /// let permit = tx.reserve().await.unwrap();
+ /// // Reserve capacity
+ /// let permit = tx.reserve().await.unwrap();
///
- /// // Trying to send directly on the `tx` will fail due to no
- /// // available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send directly on the `tx` will fail due to no
+ /// // available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Send a message on the permit
- /// permit.send(456);
+ /// // Send a message on the permit
+ /// permit.send(456);
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
- /// }
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// # }
/// ```
pub fn send(self, value: T) {
use std::mem;
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, mut rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, mut rx) = mpsc::channel(1);
///
- /// // Reserve capacity
- /// let permit = tx.reserve_owned().await.unwrap();
+ /// // Reserve capacity
+ /// let permit = tx.reserve_owned().await.unwrap();
///
- /// // Send a message on the permit, returning the sender.
- /// let tx = permit.send(456);
+ /// // Send a message on the permit, returning the sender.
+ /// let tx = permit.send(456);
///
- /// // The value sent on the permit is received
- /// assert_eq!(rx.recv().await.unwrap(), 456);
+ /// // The value sent on the permit is received
+ /// assert_eq!(rx.recv().await.unwrap(), 456);
///
- /// // We may now reuse `tx` to send another message.
- /// tx.send(789).await.unwrap();
- /// }
+ /// // We may now reuse `tx` to send another message.
+ /// tx.send(789).await.unwrap();
+ /// # }
/// ```
pub fn send(mut self, value: T) -> Sender<T> {
let chan = self.chan.take().unwrap_or_else(|| {
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel(1);
///
- /// // Clone the sender and reserve capacity
- /// let permit = tx.clone().reserve_owned().await.unwrap();
+ /// // Clone the sender and reserve capacity
+ /// let permit = tx.clone().reserve_owned().await.unwrap();
///
- /// // Trying to send on the original `tx` will fail, since the `permit`
- /// // has reserved all the available capacity.
- /// assert!(tx.try_send(123).is_err());
+ /// // Trying to send on the original `tx` will fail, since the `permit`
+ /// // has reserved all the available capacity.
+ /// assert!(tx.try_send(123).is_err());
///
- /// // Release the permit without sending a message, returning the clone
- /// // of the sender.
- /// let tx2 = permit.release();
+ /// // Release the permit without sending a message, returning the clone
+ /// // of the sender.
+ /// let tx2 = permit.release();
///
- /// // We may now reuse `tx` to send another message.
- /// tx.send(789).await.unwrap();
- /// # drop(rx); drop(tx2);
- /// }
+ /// // We may now reuse `tx` to send another message.
+ /// tx.send(789).await.unwrap();
+ /// # drop(rx); drop(tx2);
+ /// # }
/// ```
///
/// [`Sender`]: Sender
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel::<()>(2);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel::<()>(2);
///
- /// let permit1 = tx.clone().reserve_owned().await.unwrap();
- /// let permit2 = tx.clone().reserve_owned().await.unwrap();
- /// assert!(permit1.same_channel(&permit2));
+ /// let permit1 = tx.clone().reserve_owned().await.unwrap();
+ /// let permit2 = tx.clone().reserve_owned().await.unwrap();
+ /// assert!(permit1.same_channel(&permit2));
///
- /// let (tx2, rx2) = mpsc::channel::<()>(1);
+ /// let (tx2, rx2) = mpsc::channel::<()>(1);
///
- /// let permit3 = tx2.clone().reserve_owned().await.unwrap();
- /// assert!(!permit3.same_channel(&permit2));
- /// }
+ /// let permit3 = tx2.clone().reserve_owned().await.unwrap();
+ /// assert!(!permit3.same_channel(&permit2));
+ /// # }
/// ```
pub fn same_channel(&self, other: &Self) -> bool {
self.chan
/// ```
/// use tokio::sync::mpsc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = mpsc::channel::<()>(1);
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::channel::<()>(1);
///
- /// let permit = tx.clone().reserve_owned().await.unwrap();
- /// assert!(permit.same_channel_as_sender(&tx));
+ /// let permit = tx.clone().reserve_owned().await.unwrap();
+ /// assert!(permit.same_channel_as_sender(&tx));
///
- /// let (tx2, rx2) = mpsc::channel::<()>(1);
- /// assert!(!permit.same_channel_as_sender(&tx2));
- /// }
+ /// let (tx2, rx2) = mpsc::channel::<()>(1);
+ /// assert!(!permit.same_channel_as_sender(&tx2));
+ /// # }
/// ```
pub fn same_channel_as_sender(&self, sender: &Sender<T>) -> bool {
self.chan
/// ```
/// 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>>,
/// ```
/// 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:
/// ```
/// 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;
/// ```
/// 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();
- ///
- /// // 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);
- ///
- /// 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);
- ///
- /// // 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);
- /// }
+ /// # #[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);
+ ///
+ /// // 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();
+ /// });
+ ///
+ /// // '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);
+ /// # }
/// ```
pub async fn recv_many(&mut self, buffer: &mut Vec<T>, limit: usize) -> usize {
use std::future::poll_fn;
/// 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()
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::thread;
/// use tokio::sync::mpsc;
///
/// let _ = tx.send(10);
/// sync_code.join().unwrap();
/// }
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// ```
/// 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()
/// ```
/// 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 {
/// ```
/// 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()
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::task::{Context, Poll};
/// use std::pin::Pin;
/// use tokio::sync::mpsc;
/// }
/// }
///
- /// #[tokio::main]
- /// 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,
- /// };
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = mpsc::unbounded_channel::<i32>();
+ /// let mut buffer = Vec::new();
///
- /// for i in 0..10 {
- /// tx.send(i).expect("Unable to send integer");
- /// }
+ /// let my_receiver_future = MyReceiverFuture {
+ /// receiver: rx,
+ /// buffer: &mut buffer,
+ /// limit: 3,
+ /// };
///
- /// 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,
/// ```
/// 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);
- /// });
- ///
- /// futures::join!(
- /// tx1.closed(),
- /// tx2.closed(),
- /// tx3.closed(),
- /// tx4.closed(),
- /// tx5.closed()
- /// );
- //// println!("Receiver dropped");
- /// }
+ /// # #[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");
+ /// # }
/// ```
pub async fn closed(&self) {
self.chan.closed().await;
/// 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;
+/// # }
/// ```
///
///
/// 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);
/// }
+/// });
+/// }
+///
+/// loop {
+/// if *count.lock().await >= 50 {
+/// break;
/// }
-/// println!("Count hit 50.");
/// }
+/// 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
/// ```
/// 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 {
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::sync::Arc;
/// use tokio::sync::Mutex;
///
/// let n = mutex.try_lock().unwrap();
/// assert_eq!(*n, 2);
/// }
- ///
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::sync::Arc;
/// use tokio::sync::Mutex;
///
/// let n = mutex.try_lock().unwrap();
/// assert_eq!(*n, 2);
/// }
- ///
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// 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
/// ```
/// 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
/// #[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));
///
/// #[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));
///
/// guard
/// }
/// #
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// # let mutex = Mutex::new(0u32);
/// # let guard = mutex.lock().await;
/// #[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)));
///
/// #[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)));
///
/// guard
/// }
/// #
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// # let mutex = Arc::new(Mutex::new(0u32));
/// # let guard = mutex.lock_owned().await;
/// 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.
/// 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
/// 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
/// 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"))]
/// 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();
///
/// 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.
/// }).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,
/// }).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
/// }).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
//! ```
//! use tokio::sync::oneshot;
//!
-//! #[tokio::main]
-//! async fn main() {
-//! let (tx, rx) = oneshot::channel();
-//!
-//! tokio::spawn(async move {
-//! if let Err(_) = tx.send(3) {
-//! println!("the receiver dropped");
-//! }
-//! });
+//! # #[tokio::main(flavor = "current_thread")]
+//! # async fn main() {
+//! let (tx, rx) = oneshot::channel();
//!
-//! 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
//! ```
//! 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
//! 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
//! }
//! }
//!
-//! #[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;
/// ```
/// use tokio::sync::oneshot;
///
-/// #[tokio::main]
-/// async fn main() {
-/// let (tx, rx) = oneshot::channel();
-///
-/// tokio::spawn(async move {
-/// if let Err(_) = tx.send(3) {
-/// println!("the receiver dropped");
-/// }
-/// });
+/// # #[tokio::main(flavor = "current_thread")]
+/// # async fn main() {
+/// let (tx, rx) = oneshot::channel();
///
-/// 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
/// ```
/// 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
/// }
/// }
///
-/// #[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
/// ```
/// use tokio::sync::oneshot;
///
-/// #[tokio::main]
-/// async fn main() {
-/// let (tx, rx) = oneshot::channel();
-///
-/// tokio::spawn(async move {
-/// if let Err(_) = tx.send(3) {
-/// println!("the receiver dropped");
-/// }
-/// });
+/// # #[tokio::main(flavor = "current_thread")]
+/// # async fn main() {
+/// let (tx, rx) = oneshot::channel();
///
-/// 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
/// ```
/// 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
/// 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> {
/// ```
/// use tokio::sync::oneshot;
///
-/// #[tokio::main]
-/// async fn main() {
-/// let (tx, rx) = oneshot::channel();
-///
-/// tokio::spawn(async move {
-/// if let Err(_) = tx.send(3) {
-/// println!("the receiver dropped");
-/// }
-/// });
+/// # #[tokio::main(flavor = "current_thread")]
+/// # async fn main() {
+/// let (tx, rx) = oneshot::channel();
///
-/// 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>) {
/// ```
/// use tokio::sync::oneshot;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let (tx, rx) = oneshot::channel();
- ///
- /// tokio::spawn(async move {
- /// if let Err(_) = tx.send(3) {
- /// println!("the receiver dropped");
- /// }
- /// });
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let (tx, rx) = oneshot::channel();
///
- /// 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();
/// ```
/// 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
/// # "hello".to_string()
/// }
///
- /// #[tokio::main]
- /// 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::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);
+ /// }
+ /// }
+ /// });
///
- /// // 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;
/// ```
/// 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();
///
/// 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));
/// 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`
/// ```
/// 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() {
///
/// 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.
/// ```
/// 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()
/// ```
/// 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.
/// ```
/// 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]
/// 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!(),
- /// }
+ /// match rx.try_recv() {
+ /// // The channel is currently empty
+ /// Err(TryRecvError::Empty) => {}
+ /// _ => unreachable!(),
+ /// }
///
- /// // Send a value
- /// tx.send("hello").unwrap();
+ /// // Send a value
+ /// tx.send("hello").unwrap();
///
- /// match rx.try_recv() {
- /// Ok(value) => assert_eq!(value, "hello"),
- /// _ => unreachable!(),
- /// }
+ /// match rx.try_recv() {
+ /// Ok(value) => assert_eq!(value, "hello"),
+ /// _ => unreachable!(),
/// }
+ /// # }
/// ```
///
/// `try_recv` when the sender dropped before sending a value
/// 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() {
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::thread;
/// use tokio::sync::oneshot;
///
/// let _ = tx.send(10);
/// sync_code.join().unwrap();
/// }
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// ```
/// 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
/// 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 {
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::sync::Arc;
/// use tokio::sync::RwLock;
///
/// // Assert uncontended.
/// assert!(rwlock.try_write().is_ok());
/// }
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// 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> {
/// 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) {
/// 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) {
/// ```
/// 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 {
/// # Examples
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use std::sync::Arc;
/// use tokio::{sync::RwLock};
///
/// let read_lock = rwlock.try_read().unwrap();
/// assert_eq!(*read_lock, 2);
/// }
+ /// # }
/// ```
#[track_caller]
#[cfg(feature = "sync")]
/// 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> {
/// ```
/// 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) {
/// 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) {
/// #[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)));
///
/// #[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)));
///
/// #[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)));
///
/// #[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)));
///
/// #[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)));
///
/// #[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)));
///
/// #[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)));
///
/// # 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));
///
/// 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));
///
/// #[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)));
///
/// #[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)));
///
/// OwnedRwLockMappedWriteGuard,
/// };
///
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// let lock = Arc::new(RwLock::new(1));
///
/// #[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));
///
/// #[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));
///
/// #[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));
///
/// #[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));
///
/// #[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));
///
/// #[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));
///
/// # 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));
///
/// #[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));
///
/// #[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));
///
/// ```
/// 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
/// 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;
/// 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
/// 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.
-/// // ...
-///
-/// 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.
-/// // ...
+/// # #[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.
+/// // ...
+/// # }
/// # async fn send_request(task_id: usize) {
/// # // Send request.
/// # }
/// (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;
/// # async fn handle_connection(_socket: &mut tokio::net::TcpStream) {
/// # // Do work
/// # }
+/// # }
/// ```
///
/// ## Prevent tests from running in parallel
/// }
/// }
///
-/// #[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
/// ```
/// 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
/// ```
/// 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
/// 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();
- ///
- /// 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();
- /// }
+ /// # #[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();
/// }
+ /// # }
/// ```
///
/// [`Arc`]: std::sync::Arc
/// 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();
- ///
- /// 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();
- /// }
+ /// # #[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();
+ /// }
+ /// # }
/// ```
///
/// [`Arc`]: std::sync::Arc
/// 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();
///
/// 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
/// 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
/// 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
/// 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
//! ```
//! 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
/// ```
/// use tokio::sync::watch;
///
- /// #[tokio::main]
- /// 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());
- ///
- /// // 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());
- ///
- /// // 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());
+ /// # #[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());
+ ///
+ /// // 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());
+ ///
+ /// // 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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
/// ```
/// 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 {
/// ```
/// 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
/// 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::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());
- /// }
+ /// # #[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();
+ /// });
+ ///
+ /// rx.changed().await.unwrap();
+ /// assert_eq!(100, *rx.borrow());
+ /// # }
/// ```
pub fn subscribe(&self) -> Receiver<T> {
let shared = self.shared.clone();
/// ```
/// 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)
/// ```
/// 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)
//! Tokio. For example:
//!
//! ```
-//! # #[tokio::main]
+//! # #[tokio::main(flavor = "current_thread")]
//! # async fn main() {
//! use tokio::{task, sync::mpsc};
//!
/// ```
/// 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 });
-/// }
+/// 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;
-/// }
+/// 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 {
+/// assert!(seen[i]);
/// }
+/// # }
/// ```
///
/// # Task ID guarantees
/// Spawn multiple blocking tasks and wait for them.
///
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::task::JoinSet;
///
/// #[tokio::main]
/// assert!(seen[i]);
/// }
/// }
+ /// # }
/// ```
///
/// # Panics
/// use tokio::task::JoinSet;
/// use std::time::Duration;
///
- /// #[tokio::main]
- /// 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
- /// });
- /// }
+ /// # #[tokio::main(flavor = "current_thread")]
+ /// # async fn main() {
+ /// let mut set = JoinSet::new();
///
- /// 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.
/// 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});
- /// }
+ /// 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}"),
- /// }
+ /// 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);
/// }
+ /// assert_eq!(output.len(),3);
+ /// # }
/// ```
/// [`join_next`]: fn@Self::join_next
/// [`JoinError::id`]: fn@crate::task::JoinError::id
/// ```
/// 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;
-/// }
+/// 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 {
+/// assert!(seen[i]);
/// }
+/// # }
/// ```
///
/// [`collect`]: std::iter::Iterator::collect
/// 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
/// use tokio::{task, time};
/// use std::rc::Rc;
///
- /// #[tokio::main]
- /// async fn main() {
- /// let nonsend_data = Rc::new("world");
- /// let local = task::LocalSet::new();
+ /// # #[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)
- /// });
+ /// 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)
- /// });
+ /// local.spawn_local(async move {
+ /// time::sleep(time::Duration::from_millis(100)).await;
+ /// println!("goodbye {}", nonsend_data)
+ /// });
///
- /// // ...
+ /// // ...
///
- /// local.await;
- /// }
+ /// local.await;
+ /// # }
/// ```
/// **Note:** Awaiting a `LocalSet` can only be done inside
/// `#[tokio::main]`, `#[tokio::test]` or directly inside a call to
///
/// 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;
/// let eleven = response.await.unwrap();
/// assert_eq!(eleven, 11);
/// }
+ /// # }
/// ```
///
/// [`Send`]: trait@std::marker::Send
/// 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
/// ```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]
/// 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;
///
/// ```
/// This, however, will not panic:
/// ```
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::runtime::Runtime;
/// use tokio::task;
///
/// });
/// join.await.unwrap();
/// })
+ /// # }
/// ```
///
/// [`spawn_local`]: fn@spawn_local
/// ```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
/// ```should_panic
/// use tokio::runtime::UnhandledPanic;
///
- /// # #[tokio::main]
+ /// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() {
/// tokio::task::LocalSet::new()
/// .unhandled_panic(UnhandledPanic::ShutdownRuntime)
/// ```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
//! ```
//! 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!"
//! example:
//!
//! ```
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::task;
//!
//! # #[tokio::main] async fn main() {
//! // The returned result indicates that the task failed.
//! assert!(join.await.is_err());
//! # }
+//! # }
//! ```
//!
//! `spawn`, `JoinHandle`, and `JoinError` are present when the "rt"
//! For example:
//!
//! ```
+//! # #[cfg(not(target_family = "wasm"))]
+//! # {
//! use tokio::task;
//!
//! # async fn docs() {
//!
//! assert_eq!(result, "blocking completed");
//! # }
+//! # }
//! ```
//!
//! #### `yield_now`
//! ```rust
//! use tokio::task;
//!
-//! # #[tokio::main] async fn main() {
+//! # #[tokio::main(flavor = "current_thread")]
+//! # async fn main() {
//! async {
//! task::spawn(async {
//! // ...
/// that processes each received connection.
///
/// ```no_run
+ /// # #[cfg(not(target_family = "wasm"))]
+ /// # {
/// use tokio::net::{TcpListener, TcpStream};
///
/// use std::io;
/// });
/// }
/// }
+ /// # }
/// ```
///
/// To run multiple tasks in parallel and receive their results, join
/// # 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:
/// ```
/// 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)
/// ```
/// 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 {
/// ```
/// 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)
/// ```
/// 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.
/// 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()
/// ```
/// 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 {
/// 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
///
/// 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"))]
///
/// 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);
///
/// 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());
///
/// 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);
///
/// 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);
//! 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.
//! 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()
/// ```
/// 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.
/// ```
/// 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.
/// ```
/// 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
/// ```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.