mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-16 00:00:12 +02:00
@@ -399,12 +399,13 @@ cfg_rt_core! {
|
||||
/// Sets runtime to use a simpler scheduler that runs all tasks on the current-thread.
|
||||
///
|
||||
/// The executor and all necessary drivers will all be run on the current
|
||||
/// thread during `block_on` calls.
|
||||
/// thread during [`block_on`] calls.
|
||||
///
|
||||
/// See also [the module level documentation][1], which has a section on scheduler
|
||||
/// types.
|
||||
///
|
||||
/// [1]: index.html#runtime-configurations
|
||||
/// [`block_on`]: Runtime::block_on
|
||||
pub fn basic_scheduler(&mut self) -> &mut Self {
|
||||
self.kind = Kind::Basic;
|
||||
self
|
||||
|
||||
+110
-10
@@ -31,7 +31,39 @@ pub struct Handle {
|
||||
}
|
||||
|
||||
impl Handle {
|
||||
/// Enter the runtime context.
|
||||
/// Enter the runtime context. This allows you to construct types that must
|
||||
/// have an executor available on creation such as [`Delay`] or [`TcpStream`].
|
||||
/// It will also allow you to call methods such as [`tokio::spawn`].
|
||||
///
|
||||
/// This function is also available as [`Runtime::enter`].
|
||||
///
|
||||
/// [`Delay`]: struct@crate::time::Delay
|
||||
/// [`TcpStream`]: struct@crate::net::TcpStream
|
||||
/// [`Runtime::enter`]: fn@crate::runtime::Runtime::enter
|
||||
/// [`tokio::spawn`]: fn@crate::spawn
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::runtime::Runtime;
|
||||
///
|
||||
/// fn function_that_spawns(msg: String) {
|
||||
/// // Had we not used `handle.enter` below, this would panic.
|
||||
/// tokio::spawn(async move {
|
||||
/// println!("{}", msg);
|
||||
/// });
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let rt = Runtime::new().unwrap();
|
||||
/// let handle = rt.handle().clone();
|
||||
///
|
||||
/// let s = "Hello World!".to_string();
|
||||
///
|
||||
/// // By entering the context, we tie `tokio::spawn` to this executor.
|
||||
/// handle.enter(|| function_that_spawns(s));
|
||||
/// }
|
||||
/// ```
|
||||
pub fn enter<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
@@ -110,8 +142,14 @@ cfg_rt_core! {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the spawn fails. Failure occurs if the executor
|
||||
/// is currently at capacity and is unable to spawn a new future.
|
||||
/// This function will not panic unless task execution is disabled on the
|
||||
/// executor. This can only happen if the runtime was built using
|
||||
/// [`Builder`] without picking either [`basic_scheduler`] or
|
||||
/// [`threaded_scheduler`].
|
||||
///
|
||||
/// [`Builder`]: struct@crate::runtime::Builder
|
||||
/// [`threaded_scheduler`]: fn@crate::runtime::Builder::threaded_scheduler
|
||||
/// [`basic_scheduler`]: fn@crate::runtime::Builder::basic_scheduler
|
||||
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
F: Future + Send + 'static,
|
||||
@@ -127,26 +165,47 @@ cfg_rt_core! {
|
||||
/// complete, and yielding its resolved result. Any tasks or timers which
|
||||
/// the future spawns internally will be executed on the runtime.
|
||||
///
|
||||
/// This method should not be called from an asynchronous context.
|
||||
/// If the provided executor currently has no active core thread, this
|
||||
/// function might hang until a core thread is added. This is not a
|
||||
/// concern when using the [threaded scheduler], as it always has active
|
||||
/// core threads, but if you use the [basic scheduler], some other
|
||||
/// thread must currently be inside a call to [`Runtime::block_on`].
|
||||
/// See also [the module level documentation][1], which has a section on
|
||||
/// scheduler types.
|
||||
///
|
||||
/// This method may not be called from an asynchronous context.
|
||||
///
|
||||
/// [threaded scheduler]: fn@crate::runtime::Builder::threaded_scheduler
|
||||
/// [basic scheduler]: fn@crate::runtime::Builder::basic_scheduler
|
||||
/// [`Runtime::block_on`]: fn@crate::runtime::Runtime::block_on
|
||||
/// [1]: index.html#runtime-configurations
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the executor is at capacity, if the provided
|
||||
/// future panics, or if called within an asynchronous execution context.
|
||||
/// This function panics if the provided future panics, or if called
|
||||
/// within an asynchronous execution context.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// Using `block_on` with the [threaded scheduler].
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::runtime::Runtime;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// // Create the runtime
|
||||
/// // Create the runtime.
|
||||
/// //
|
||||
/// // If the rt-threaded feature is enabled, this creates a threaded
|
||||
/// // scheduler by default.
|
||||
/// let rt = Runtime::new().unwrap();
|
||||
/// let handle = rt.handle().clone();
|
||||
///
|
||||
/// // Use the runtime from another thread
|
||||
/// // Use the runtime from another thread.
|
||||
/// let th = thread::spawn(move || {
|
||||
/// // Execute the future, blocking the current thread until completion
|
||||
/// // Execute the future, blocking the current thread until completion.
|
||||
/// //
|
||||
/// // This example uses the threaded scheduler, so no concurrent call to
|
||||
/// // `rt.block_on` is required.
|
||||
/// handle.block_on(async {
|
||||
/// println!("hello");
|
||||
/// });
|
||||
@@ -154,6 +213,47 @@ cfg_rt_core! {
|
||||
///
|
||||
/// th.join().unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Using the [basic scheduler] requires a concurrent call to
|
||||
/// [`Runtime::block_on`]:
|
||||
///
|
||||
/// [threaded scheduler]: fn@crate::runtime::Builder::threaded_scheduler
|
||||
/// [basic scheduler]: fn@crate::runtime::Builder::basic_scheduler
|
||||
/// [`Runtime::block_on`]: fn@crate::runtime::Runtime::block_on
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::runtime::Builder;
|
||||
/// use tokio::sync::oneshot;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// // Create the runtime.
|
||||
/// let mut rt = Builder::new()
|
||||
/// .enable_all()
|
||||
/// .basic_scheduler()
|
||||
/// .build()
|
||||
/// .unwrap();
|
||||
///
|
||||
/// let handle = rt.handle().clone();
|
||||
///
|
||||
/// // Signal main thread when task has finished.
|
||||
/// let (send, recv) = oneshot::channel();
|
||||
///
|
||||
/// // Use the runtime from another thread.
|
||||
/// let th = thread::spawn(move || {
|
||||
/// // Execute the future, blocking the current thread until completion.
|
||||
/// handle.block_on(async {
|
||||
/// send.send("done").unwrap();
|
||||
/// });
|
||||
/// });
|
||||
///
|
||||
/// // The basic scheduler is used, so the thread above might hang if we
|
||||
/// // didn't call block_on on the rt too.
|
||||
/// rt.block_on(async {
|
||||
/// assert_eq!(recv.await.unwrap(), "done");
|
||||
/// });
|
||||
/// # th.join().unwrap();
|
||||
/// ```
|
||||
///
|
||||
pub fn block_on<F: Future>(&self, future: F) -> F::Output {
|
||||
self.enter(|| {
|
||||
let mut enter = crate::runtime::enter(true);
|
||||
|
||||
@@ -379,8 +379,14 @@ impl Runtime {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the spawn fails. Failure occurs if the executor
|
||||
/// is currently at capacity and is unable to spawn a new future.
|
||||
/// This function will not panic unless task execution is disabled on the
|
||||
/// executor. This can only happen if the runtime was built using
|
||||
/// [`Builder`] without picking either [`basic_scheduler`] or
|
||||
/// [`threaded_scheduler`].
|
||||
///
|
||||
/// [`Builder`]: struct@Builder
|
||||
/// [`threaded_scheduler`]: fn@Builder::threaded_scheduler
|
||||
/// [`basic_scheduler`]: fn@Builder::basic_scheduler
|
||||
#[cfg(feature = "rt-core")]
|
||||
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
@@ -407,12 +413,12 @@ impl Runtime {
|
||||
/// configured. [`runtime::Handle::block_on`][handle] provides a version
|
||||
/// that takes `&self`.
|
||||
///
|
||||
/// This method should not be called from an asynchronous context.
|
||||
/// This method may not be called from an asynchronous context.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the executor is at capacity, if the provided
|
||||
/// future panics, or if called within an asynchronous execution context.
|
||||
/// This function panics if the provided future panics, or if called within an
|
||||
/// asynchronous execution context.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -441,7 +447,38 @@ impl Runtime {
|
||||
})
|
||||
}
|
||||
|
||||
/// Enter the runtime context.
|
||||
/// Enter the runtime context. This allows you to construct types that must
|
||||
/// have an executor available on creation such as [`Delay`] or [`TcpStream`].
|
||||
/// It will also allow you to call methods such as [`tokio::spawn`].
|
||||
///
|
||||
/// This function is also available as [`Handle::enter`].
|
||||
///
|
||||
/// [`Delay`]: struct@crate::time::Delay
|
||||
/// [`TcpStream`]: struct@crate::net::TcpStream
|
||||
/// [`Handle::enter`]: fn@crate::runtime::Handle::enter
|
||||
/// [`tokio::spawn`]: fn@crate::spawn
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use tokio::runtime::Runtime;
|
||||
///
|
||||
/// fn function_that_spawns(msg: String) {
|
||||
/// // Had we not used `rt.enter` below, this would panic.
|
||||
/// tokio::spawn(async move {
|
||||
/// println!("{}", msg);
|
||||
/// });
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let rt = Runtime::new().unwrap();
|
||||
///
|
||||
/// let s = "Hello World!".to_string();
|
||||
///
|
||||
/// // By entering the context, we tie `tokio::spawn` to this executor.
|
||||
/// rt.enter(|| function_that_spawns(s));
|
||||
/// }
|
||||
/// ```
|
||||
pub fn enter<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
@@ -476,7 +513,7 @@ impl Runtime {
|
||||
/// Usually, dropping a `Runtime` handle is sufficient as tasks are able to
|
||||
/// shutdown in a timely fashion. However, dropping a `Runtime` will wait
|
||||
/// indefinitely for all tasks to terminate, and there are cases where a long
|
||||
/// blocking task has been spawned which can block dropping `Runtime`.
|
||||
/// blocking task has been spawned, which can block dropping `Runtime`.
|
||||
///
|
||||
/// In this case, calling `shutdown_timeout` with an explicit wait timeout
|
||||
/// can work. The `shutdown_timeout` will signal all tasks to shutdown and
|
||||
|
||||
Reference in New Issue
Block a user