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:
Carl Lerche
2019-12-01 12:49:38 -08:00
committed by GitHub
parent af07f5bee7
commit 8b60c5386a
8 changed files with 291 additions and 272 deletions
+9
View File
@@ -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")]
+1
View File
@@ -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,
+5 -3
View File
@@ -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
View File
@@ -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> {}
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
} }