mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-07 00:00:08 +02:00
doc: fix documented feature flags for tokio::task (#1876)
Some feature flags are missing and some are duplicated. Closes #1836
This commit is contained in:
@@ -210,6 +210,15 @@ macro_rules! cfg_not_sync {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cfg_rt_core {
|
macro_rules! cfg_rt_core {
|
||||||
|
($($item:item)*) => {
|
||||||
|
$(
|
||||||
|
#[cfg(feature = "rt-core")]
|
||||||
|
$item
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! doc_rt_core {
|
||||||
($($item:item)*) => {
|
($($item:item)*) => {
|
||||||
$(
|
$(
|
||||||
#[cfg(feature = "rt-core")]
|
#[cfg(feature = "rt-core")]
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ cfg_rt_threaded! {
|
|||||||
/// });
|
/// });
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "blocking")))]
|
||||||
pub fn block_in_place<F, R>(f: F) -> R
|
pub fn block_in_place<F, R>(f: F) -> R
|
||||||
where
|
where
|
||||||
F: FnOnce() -> R,
|
F: FnOnce() -> R,
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ use std::any::Any;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
/// Task failed to execute to completion.
|
doc_rt_core! {
|
||||||
pub struct JoinError {
|
/// Task failed to execute to completion.
|
||||||
repr: Repr,
|
pub struct JoinError {
|
||||||
|
repr: Repr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Repr {
|
enum Repr {
|
||||||
|
|||||||
+73
-71
@@ -7,77 +7,79 @@ use std::marker::PhantomData;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
/// An owned permission to join on a task (await its termination).
|
doc_rt_core! {
|
||||||
///
|
/// An owned permission to join on a task (await its termination).
|
||||||
/// This can be thought of as the equivalent of [`std::thread::JoinHandle`] for
|
///
|
||||||
/// a task rather than a thread.
|
/// This can be thought of as the equivalent of [`std::thread::JoinHandle`] for
|
||||||
///
|
/// a task rather than a thread.
|
||||||
/// A `JoinHandle` *detaches* the associated task when it is dropped, which
|
///
|
||||||
/// means that there is no longer any handle to the task, and no way to `join`
|
/// A `JoinHandle` *detaches* the associated task when it is dropped, which
|
||||||
/// on it.
|
/// means that there is no longer any handle to the task, and no way to `join`
|
||||||
///
|
/// on it.
|
||||||
/// This `struct` is created by the [`task::spawn`] and [`task::spawn_blocking`]
|
///
|
||||||
/// functions.
|
/// This `struct` is created by the [`task::spawn`] and [`task::spawn_blocking`]
|
||||||
///
|
/// functions.
|
||||||
/// # Examples
|
///
|
||||||
///
|
/// # Examples
|
||||||
/// Creation from [`task::spawn`]:
|
///
|
||||||
///
|
/// Creation from [`task::spawn`]:
|
||||||
/// ```
|
///
|
||||||
/// use tokio::task;
|
/// ```
|
||||||
///
|
/// use tokio::task;
|
||||||
/// # async fn doc() {
|
///
|
||||||
/// let join_handle: task::JoinHandle<_> = task::spawn(async {
|
/// # async fn doc() {
|
||||||
/// // some work here
|
/// let join_handle: task::JoinHandle<_> = task::spawn(async {
|
||||||
/// });
|
/// // some work here
|
||||||
/// # }
|
/// });
|
||||||
/// ```
|
/// # }
|
||||||
///
|
/// ```
|
||||||
/// Creation from [`task::spawn_blocking`]:
|
///
|
||||||
///
|
/// Creation from [`task::spawn_blocking`]:
|
||||||
/// ```
|
///
|
||||||
/// use tokio::task;
|
/// ```
|
||||||
///
|
/// use tokio::task;
|
||||||
/// # async fn doc() {
|
///
|
||||||
/// let join_handle: task::JoinHandle<_> = task::spawn_blocking(|| {
|
/// # async fn doc() {
|
||||||
/// // some blocking work here
|
/// let join_handle: task::JoinHandle<_> = task::spawn_blocking(|| {
|
||||||
/// });
|
/// // some blocking work here
|
||||||
/// # }
|
/// });
|
||||||
/// ```
|
/// # }
|
||||||
///
|
/// ```
|
||||||
/// Child being detached and outliving its parent:
|
///
|
||||||
///
|
/// Child being detached and outliving its parent:
|
||||||
/// ```no_run
|
///
|
||||||
/// use tokio::task;
|
/// ```no_run
|
||||||
/// use tokio::time;
|
/// use tokio::task;
|
||||||
/// use std::time::Duration;
|
/// use tokio::time;
|
||||||
///
|
/// use std::time::Duration;
|
||||||
/// # #[tokio::main] async fn main() {
|
///
|
||||||
/// let original_task = task::spawn(async {
|
/// # #[tokio::main] async fn main() {
|
||||||
/// let _detached_task = task::spawn(async {
|
/// let original_task = task::spawn(async {
|
||||||
/// // Here we sleep to make sure that the first task returns before.
|
/// let _detached_task = task::spawn(async {
|
||||||
/// time::delay_for(Duration::from_millis(10)).await;
|
/// // Here we sleep to make sure that the first task returns before.
|
||||||
/// // This will be called, even though the JoinHandle is dropped.
|
/// time::delay_for(Duration::from_millis(10)).await;
|
||||||
/// println!("♫ Still alive ♫");
|
/// // This will be called, even though the JoinHandle is dropped.
|
||||||
/// });
|
/// println!("♫ Still alive ♫");
|
||||||
/// });
|
/// });
|
||||||
///
|
/// });
|
||||||
/// original_task.await.expect("The task being joined has panicked");
|
///
|
||||||
/// println!("Original task is joined.");
|
/// original_task.await.expect("The task being joined has panicked");
|
||||||
///
|
/// println!("Original task is joined.");
|
||||||
/// // We make sure that the new task has time to run, before the main
|
///
|
||||||
/// // task returns.
|
/// // We make sure that the new task has time to run, before the main
|
||||||
///
|
/// // task returns.
|
||||||
/// time::delay_for(Duration::from_millis(1000)).await;
|
///
|
||||||
/// # }
|
/// time::delay_for(Duration::from_millis(1000)).await;
|
||||||
/// ```
|
/// # }
|
||||||
///
|
/// ```
|
||||||
/// [`task::spawn`]: crate::task::spawn()
|
///
|
||||||
/// [`task::spawn_blocking`]: crate::task::spawn_blocking
|
/// [`task::spawn`]: crate::task::spawn()
|
||||||
/// [`std::thread::JoinHandle`]: std::thread::JoinHandle
|
/// [`task::spawn_blocking`]: crate::task::spawn_blocking
|
||||||
pub struct JoinHandle<T> {
|
/// [`std::thread::JoinHandle`]: std::thread::JoinHandle
|
||||||
raw: Option<RawTask>,
|
pub struct JoinHandle<T> {
|
||||||
_p: PhantomData<T>,
|
raw: Option<RawTask>,
|
||||||
|
_p: PhantomData<T>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Send> Send for JoinHandle<T> {}
|
unsafe impl<T: Send> Send for JoinHandle<T> {}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use std::sync::Mutex;
|
|||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
cfg_rt_util! {
|
cfg_rt_util! {
|
||||||
/// A set of tasks which are executed on the same thread.
|
/// A set of tasks which are executed on the same thread.
|
||||||
///
|
///
|
||||||
|
|||||||
+131
-131
@@ -216,20 +216,40 @@ cfg_blocking! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod core;
|
|
||||||
use self::core::Cell;
|
|
||||||
pub(crate) use self::core::Header;
|
|
||||||
|
|
||||||
mod error;
|
|
||||||
pub use self::error::JoinError;
|
|
||||||
|
|
||||||
mod harness;
|
|
||||||
use self::harness::Harness;
|
|
||||||
|
|
||||||
cfg_rt_core! {
|
cfg_rt_core! {
|
||||||
|
mod core;
|
||||||
|
use self::core::Cell;
|
||||||
|
pub(crate) use self::core::Header;
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
pub use self::error::JoinError;
|
||||||
|
|
||||||
|
mod harness;
|
||||||
|
use self::harness::Harness;
|
||||||
|
|
||||||
mod join;
|
mod join;
|
||||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
|
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
|
||||||
pub use self::join::JoinHandle;
|
pub use self::join::JoinHandle;
|
||||||
|
|
||||||
|
mod list;
|
||||||
|
pub(crate) use self::list::OwnedList;
|
||||||
|
|
||||||
|
mod raw;
|
||||||
|
use self::raw::RawTask;
|
||||||
|
|
||||||
|
mod spawn;
|
||||||
|
pub use spawn::spawn;
|
||||||
|
|
||||||
|
mod stack;
|
||||||
|
pub(crate) use self::stack::TransferStack;
|
||||||
|
|
||||||
|
mod state;
|
||||||
|
use self::state::{Snapshot, State};
|
||||||
|
|
||||||
|
mod waker;
|
||||||
|
|
||||||
|
mod yield_now;
|
||||||
|
pub use yield_now::yield_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_rt_util! {
|
cfg_rt_util! {
|
||||||
@@ -237,98 +257,58 @@ cfg_rt_util! {
|
|||||||
pub use local::{spawn_local, LocalSet};
|
pub use local::{spawn_local, LocalSet};
|
||||||
}
|
}
|
||||||
|
|
||||||
mod list;
|
|
||||||
pub(crate) use self::list::OwnedList;
|
|
||||||
|
|
||||||
mod raw;
|
|
||||||
use self::raw::RawTask;
|
|
||||||
|
|
||||||
cfg_rt_core! {
|
cfg_rt_core! {
|
||||||
mod spawn;
|
/// Unit tests
|
||||||
pub use spawn::spawn;
|
#[cfg(test)]
|
||||||
}
|
mod tests;
|
||||||
|
|
||||||
mod stack;
|
use std::future::Future;
|
||||||
pub(crate) use self::stack::TransferStack;
|
use std::marker::PhantomData;
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
use std::{fmt, mem};
|
||||||
|
|
||||||
mod state;
|
/// An owned handle to the task, tracked by ref count
|
||||||
use self::state::{Snapshot, State};
|
pub(crate) struct Task<S: 'static> {
|
||||||
|
raw: RawTask,
|
||||||
|
_p: PhantomData<S>,
|
||||||
|
}
|
||||||
|
|
||||||
mod waker;
|
unsafe impl<S: ScheduleSendOnly + 'static> Send for Task<S> {}
|
||||||
|
|
||||||
mod yield_now;
|
/// Task result sent back
|
||||||
pub use yield_now::yield_now;
|
pub(crate) type Result<T> = std::result::Result<T, JoinError>;
|
||||||
|
|
||||||
/// Unit tests
|
pub(crate) trait Schedule: Sized + 'static {
|
||||||
#[cfg(test)]
|
/// Bind a task to the executor.
|
||||||
mod tests;
|
///
|
||||||
|
/// Guaranteed to be called from the thread that called `poll` on the task.
|
||||||
|
fn bind(&self, task: &Task<Self>);
|
||||||
|
|
||||||
use std::future::Future;
|
/// The task has completed work and is ready to be released. The scheduler
|
||||||
use std::marker::PhantomData;
|
/// is free to drop it whenever.
|
||||||
use std::ptr::NonNull;
|
fn release(&self, task: Task<Self>);
|
||||||
use std::{fmt, mem};
|
|
||||||
|
|
||||||
/// An owned handle to the task, tracked by ref count
|
/// The has been completed by the executor it was bound to.
|
||||||
pub(crate) struct Task<S: 'static> {
|
fn release_local(&self, task: &Task<Self>);
|
||||||
raw: RawTask,
|
|
||||||
_p: PhantomData<S>,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl<S: ScheduleSendOnly + 'static> Send for Task<S> {}
|
/// Schedule the task
|
||||||
|
fn schedule(&self, task: Task<Self>);
|
||||||
|
}
|
||||||
|
|
||||||
/// Task result sent back
|
/// Marker trait indicating that a scheduler can only schedule tasks which
|
||||||
pub(crate) type Result<T> = std::result::Result<T, JoinError>;
|
/// implement `Send`.
|
||||||
|
|
||||||
pub(crate) trait Schedule: Sized + 'static {
|
|
||||||
/// Bind a task to the executor.
|
|
||||||
///
|
///
|
||||||
/// Guaranteed to be called from the thread that called `poll` on the task.
|
/// Schedulers that implement this trait may not schedule `!Send` futures. If
|
||||||
fn bind(&self, task: &Task<Self>);
|
/// trait is implemented, the corresponding `Task` type will implement `Send`.
|
||||||
|
pub(crate) trait ScheduleSendOnly: Schedule + Send + Sync {}
|
||||||
|
|
||||||
/// The task has completed work and is ready to be released. The scheduler
|
/// Create a new task with an associated join handle
|
||||||
/// is free to drop it whenever.
|
pub(crate) fn joinable<T, S>(task: T) -> (Task<S>, JoinHandle<T::Output>)
|
||||||
fn release(&self, task: Task<Self>);
|
|
||||||
|
|
||||||
/// The has been completed by the executor it was bound to.
|
|
||||||
fn release_local(&self, task: &Task<Self>);
|
|
||||||
|
|
||||||
/// Schedule the task
|
|
||||||
fn schedule(&self, task: Task<Self>);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Marker trait indicating that a scheduler can only schedule tasks which
|
|
||||||
/// implement `Send`.
|
|
||||||
///
|
|
||||||
/// Schedulers that implement this trait may not schedule `!Send` futures. If
|
|
||||||
/// trait is implemented, the corresponding `Task` type will implement `Send`.
|
|
||||||
pub(crate) trait ScheduleSendOnly: Schedule + Send + Sync {}
|
|
||||||
|
|
||||||
/// Create a new task with an associated join handle
|
|
||||||
pub(crate) fn joinable<T, S>(task: T) -> (Task<S>, JoinHandle<T::Output>)
|
|
||||||
where
|
|
||||||
T: Future + Send + 'static,
|
|
||||||
S: ScheduleSendOnly,
|
|
||||||
{
|
|
||||||
let raw = RawTask::new_joinable::<_, S>(task);
|
|
||||||
|
|
||||||
let task = Task {
|
|
||||||
raw,
|
|
||||||
_p: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
let join = JoinHandle::new(raw);
|
|
||||||
|
|
||||||
(task, join)
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_rt_util! {
|
|
||||||
/// Create a new `!Send` task with an associated join handle
|
|
||||||
pub(crate) fn joinable_local<T, S>(task: T) -> (Task<S>, JoinHandle<T::Output>)
|
|
||||||
where
|
where
|
||||||
T: Future + 'static,
|
T: Future + Send + 'static,
|
||||||
S: Schedule,
|
S: ScheduleSendOnly,
|
||||||
{
|
{
|
||||||
let raw = RawTask::new_joinable_local::<_, S>(task);
|
let raw = RawTask::new_joinable::<_, S>(task);
|
||||||
|
|
||||||
let task = Task {
|
let task = Task {
|
||||||
raw,
|
raw,
|
||||||
@@ -339,61 +319,81 @@ cfg_rt_util! {
|
|||||||
|
|
||||||
(task, join)
|
(task, join)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: 'static> Task<S> {
|
cfg_rt_util! {
|
||||||
pub(crate) unsafe fn from_raw(ptr: NonNull<Header>) -> Task<S> {
|
/// Create a new `!Send` task with an associated join handle
|
||||||
Task {
|
pub(crate) fn joinable_local<T, S>(task: T) -> (Task<S>, JoinHandle<T::Output>)
|
||||||
raw: RawTask::from_raw(ptr),
|
where
|
||||||
_p: PhantomData,
|
T: Future + 'static,
|
||||||
|
S: Schedule,
|
||||||
|
{
|
||||||
|
let raw = RawTask::new_joinable_local::<_, S>(task);
|
||||||
|
|
||||||
|
let task = Task {
|
||||||
|
raw,
|
||||||
|
_p: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
let join = JoinHandle::new(raw);
|
||||||
|
|
||||||
|
(task, join)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn header(&self) -> &Header {
|
impl<S: 'static> Task<S> {
|
||||||
self.raw.header()
|
pub(crate) unsafe fn from_raw(ptr: NonNull<Header>) -> Task<S> {
|
||||||
}
|
Task {
|
||||||
|
raw: RawTask::from_raw(ptr),
|
||||||
|
_p: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn into_raw(self) -> NonNull<Header> {
|
pub(crate) fn header(&self) -> &Header {
|
||||||
let raw = self.raw.into_raw();
|
self.raw.header()
|
||||||
mem::forget(self);
|
}
|
||||||
raw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Schedule> Task<S> {
|
pub(crate) fn into_raw(self) -> NonNull<Header> {
|
||||||
/// Returns `self` when the task needs to be immediately re-scheduled
|
let raw = self.raw.into_raw();
|
||||||
pub(crate) fn run<F>(self, mut executor: F) -> Option<Self>
|
|
||||||
where
|
|
||||||
F: FnMut() -> Option<NonNull<S>>,
|
|
||||||
{
|
|
||||||
if unsafe {
|
|
||||||
self.raw
|
|
||||||
.poll(&mut || executor().map(|ptr| ptr.cast::<()>()))
|
|
||||||
} {
|
|
||||||
Some(self)
|
|
||||||
} else {
|
|
||||||
// Cleaning up the `Task` instance is done from within the poll
|
|
||||||
// function.
|
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
None
|
raw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pre-emptively cancel the task as part of the shutdown process.
|
impl<S: Schedule> Task<S> {
|
||||||
pub(crate) fn shutdown(self) {
|
/// Returns `self` when the task needs to be immediately re-scheduled
|
||||||
self.raw.cancel_from_queue();
|
pub(crate) fn run<F>(self, mut executor: F) -> Option<Self>
|
||||||
mem::forget(self);
|
where
|
||||||
}
|
F: FnMut() -> Option<NonNull<S>>,
|
||||||
}
|
{
|
||||||
|
if unsafe {
|
||||||
|
self.raw
|
||||||
|
.poll(&mut || executor().map(|ptr| ptr.cast::<()>()))
|
||||||
|
} {
|
||||||
|
Some(self)
|
||||||
|
} else {
|
||||||
|
// Cleaning up the `Task` instance is done from within the poll
|
||||||
|
// function.
|
||||||
|
mem::forget(self);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: 'static> Drop for Task<S> {
|
/// Pre-emptively cancel the task as part of the shutdown process.
|
||||||
fn drop(&mut self) {
|
pub(crate) fn shutdown(self) {
|
||||||
self.raw.drop_task();
|
self.raw.cancel_from_queue();
|
||||||
|
mem::forget(self);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> fmt::Debug for Task<S> {
|
impl<S: 'static> Drop for Task<S> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn drop(&mut self) {
|
||||||
fmt.debug_struct("Task").finish()
|
self.raw.drop_task();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> fmt::Debug for Task<S> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt.debug_struct("Task").finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-47
@@ -3,51 +3,53 @@ use crate::task::JoinHandle;
|
|||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
|
||||||
/// Spawns a new asynchronous task, returning a
|
doc_rt_core! {
|
||||||
/// [`JoinHandle`](super::JoinHandle) for it.
|
/// Spawns a new asynchronous task, returning a
|
||||||
///
|
/// [`JoinHandle`](super::JoinHandle) for it.
|
||||||
/// Spawning a task enables the task to execute concurrently to other tasks. The
|
///
|
||||||
/// spawned task may execute on the current thread, or it may be sent to a
|
/// Spawning a task enables the task to execute concurrently to other tasks. The
|
||||||
/// different thread to be executed. The specifics depend on the current
|
/// spawned task may execute on the current thread, or it may be sent to a
|
||||||
/// [`Runtime`](crate::runtime::Runtime) configuration.
|
/// different thread to be executed. The specifics depend on the current
|
||||||
///
|
/// [`Runtime`](crate::runtime::Runtime) configuration.
|
||||||
/// # Examples
|
///
|
||||||
///
|
/// # Examples
|
||||||
/// In this example, a server is started and `spawn` is used to start a new task
|
///
|
||||||
/// that processes each received connection.
|
/// In this example, a server is started and `spawn` is used to start a new task
|
||||||
///
|
/// that processes each received connection.
|
||||||
/// ```no_run
|
///
|
||||||
/// use tokio::net::{TcpListener, TcpStream};
|
/// ```no_run
|
||||||
///
|
/// use tokio::net::{TcpListener, TcpStream};
|
||||||
/// use std::io;
|
///
|
||||||
///
|
/// use std::io;
|
||||||
/// async fn process(socket: TcpStream) {
|
///
|
||||||
/// // ...
|
/// async fn process(socket: TcpStream) {
|
||||||
/// # drop(socket);
|
/// // ...
|
||||||
/// }
|
/// # drop(socket);
|
||||||
///
|
/// }
|
||||||
/// #[tokio::main]
|
///
|
||||||
/// async fn main() -> io::Result<()> {
|
/// #[tokio::main]
|
||||||
/// let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
|
/// async fn main() -> io::Result<()> {
|
||||||
///
|
/// let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
|
||||||
/// loop {
|
///
|
||||||
/// let (socket, _) = listener.accept().await?;
|
/// loop {
|
||||||
///
|
/// let (socket, _) = listener.accept().await?;
|
||||||
/// tokio::spawn(async move {
|
///
|
||||||
/// // Process each socket concurrently.
|
/// tokio::spawn(async move {
|
||||||
/// process(socket).await
|
/// // Process each socket concurrently.
|
||||||
/// });
|
/// process(socket).await
|
||||||
/// }
|
/// });
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// }
|
||||||
///
|
/// ```
|
||||||
/// # Panics
|
///
|
||||||
///
|
/// # Panics
|
||||||
/// Panics if called from **outside** of the Tokio runtime.
|
///
|
||||||
pub fn spawn<T>(task: T) -> JoinHandle<T::Output>
|
/// Panics if called from **outside** of the Tokio runtime.
|
||||||
where
|
pub fn spawn<T>(task: T) -> JoinHandle<T::Output>
|
||||||
T: Future + Send + 'static,
|
where
|
||||||
T::Output: Send + 'static,
|
T: Future + Send + 'static,
|
||||||
{
|
T::Output: Send + 'static,
|
||||||
runtime::spawn(task)
|
{
|
||||||
|
runtime::spawn(task)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-20
@@ -2,26 +2,28 @@ use std::future::Future;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
/// Yield execution back to the Tokio runtime.
|
doc_rt_core! {
|
||||||
pub async fn yield_now() {
|
/// Yield execution back to the Tokio runtime.
|
||||||
/// Yield implementation
|
pub async fn yield_now() {
|
||||||
struct YieldNow {
|
/// Yield implementation
|
||||||
yielded: bool,
|
struct YieldNow {
|
||||||
}
|
yielded: bool,
|
||||||
|
|
||||||
impl Future for YieldNow {
|
|
||||||
type Output = ();
|
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
|
||||||
if self.yielded {
|
|
||||||
return Poll::Ready(());
|
|
||||||
}
|
|
||||||
|
|
||||||
self.yielded = true;
|
|
||||||
cx.waker().wake_by_ref();
|
|
||||||
Poll::Pending
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
YieldNow { yielded: false }.await
|
impl Future for YieldNow {
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
||||||
|
if self.yielded {
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.yielded = true;
|
||||||
|
cx.waker().wake_by_ref();
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
YieldNow { yielded: false }.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user