mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-25 00:00:18 +02:00
runtime: combine executor and runtime mods (#1734)
Now, all types are under `runtime`. `executor::util` is moved to a top level `util` module.
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
//! });
|
||||
//! ```
|
||||
|
||||
use tokio::executor::park::{Park, Unpark};
|
||||
use tokio::runtime::{Park, Unpark};
|
||||
use tokio::timer::clock::{Clock, Now};
|
||||
use tokio::timer::Timer;
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
//! Task execution related traits and utilities.
|
||||
//!
|
||||
//! In the Tokio execution model, futures are lazy. When a future is created, no
|
||||
//! work is performed. In order for the work defined by the future to happen,
|
||||
//! the future must be submitted to an executor. A future that is submitted to
|
||||
//! an executor is called a "task".
|
||||
//!
|
||||
//! The executor is responsible for ensuring that [`Future::poll`] is called
|
||||
//! whenever the task is notified. Notification happens when the internal
|
||||
//! state of a task transitions from *not ready* to *ready*. For example, a
|
||||
//! socket might have received data and a call to `read` will now be able to
|
||||
//! succeed.
|
||||
//!
|
||||
//! The specific strategy used to manage the tasks is left up to the
|
||||
//! executor. There are two main flavors of executors: single-threaded and
|
||||
//! multi-threaded. Tokio provides implementation for both of these in the
|
||||
//! [`runtime`] module.
|
||||
//!
|
||||
//! # `Executor` trait.
|
||||
//!
|
||||
//! This module provides the [`Executor`] trait (re-exported from
|
||||
//! [`tokio-executor`]), which describes the API that all executors must
|
||||
//! implement.
|
||||
//!
|
||||
//! A free [`spawn`] function is provided that allows spawning futures onto the
|
||||
//! default executor (tracked via a thread-local variable) without referencing a
|
||||
//! handle. It is expected that all executors will set a value for the default
|
||||
//! executor. This value will often be set to the executor itself, but it is
|
||||
//! possible that the default executor might be set to a different executor.
|
||||
//!
|
||||
//! For example, a single threaded executor might set the default executor to a
|
||||
//! thread pool instead of itself, allowing futures to spawn new tasks onto the
|
||||
//! thread pool when those tasks are `Send`.
|
||||
//!
|
||||
//! [`Future::poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll
|
||||
//! [notified]: https://docs.rs/futures/0.1/futures/executor/trait.Notify.html#tymethod.notify
|
||||
//! [`runtime`]: ../runtime/index.html
|
||||
//! [`tokio-executor`]: https://docs.rs/tokio-executor/0.1
|
||||
//! [`Executor`]: trait.Executor.html
|
||||
//! [`spawn`]: fn.spawn.html#[cfg(all(test, loom))]
|
||||
|
||||
// At the top due to macros
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod tests;
|
||||
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
mod enter;
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub(crate) use self::enter::enter;
|
||||
|
||||
mod global;
|
||||
pub use self::global::spawn;
|
||||
|
||||
pub mod park;
|
||||
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
mod task;
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub use self::task::{JoinError, JoinHandle};
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
mod util;
|
||||
|
||||
#[cfg(all(not(feature = "blocking"), feature = "rt-full"))]
|
||||
mod blocking;
|
||||
#[cfg(feature = "blocking")]
|
||||
pub mod blocking;
|
||||
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub(crate) mod current_thread;
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
pub(crate) mod thread_pool;
|
||||
+1
-1
@@ -91,5 +91,5 @@ where
|
||||
mod sys {
|
||||
pub(crate) use std::fs::File;
|
||||
|
||||
pub(crate) use crate::executor::blocking::{run, Blocking};
|
||||
pub(crate) use crate::runtime::blocking::{run, Blocking};
|
||||
}
|
||||
|
||||
+6
-5
@@ -72,6 +72,7 @@
|
||||
macro_rules! if_runtime {
|
||||
($($i:item)*) => ($(
|
||||
#[cfg(any(
|
||||
feature = "blocking",
|
||||
feature = "rt-full",
|
||||
feature = "rt-current-thread",
|
||||
))]
|
||||
@@ -98,7 +99,6 @@ pub mod io;
|
||||
#[cfg(feature = "net-driver")]
|
||||
pub mod net;
|
||||
|
||||
#[cfg(any(feature = "sync", feature = "blocking", feature = "rt-current-thread"))]
|
||||
mod loom;
|
||||
|
||||
pub mod prelude;
|
||||
@@ -106,6 +106,8 @@ pub mod prelude;
|
||||
#[cfg(all(feature = "process", not(loom)))]
|
||||
pub mod process;
|
||||
|
||||
pub mod runtime;
|
||||
|
||||
#[cfg(feature = "signal")]
|
||||
#[cfg(not(loom))]
|
||||
pub mod signal;
|
||||
@@ -118,14 +120,13 @@ pub mod sync;
|
||||
#[cfg(feature = "timer")]
|
||||
pub mod timer;
|
||||
|
||||
#[cfg(feature = "executor-core")]
|
||||
pub mod executor;
|
||||
#[cfg(feature = "rt-full")]
|
||||
mod util;
|
||||
|
||||
if_runtime! {
|
||||
pub mod runtime;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::executor::spawn;
|
||||
pub use crate::runtime::spawn;
|
||||
|
||||
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
||||
#[cfg(feature = "macros")]
|
||||
|
||||
@@ -12,6 +12,7 @@ pub(crate) mod cell {
|
||||
pub(crate) use super::causal_cell::{CausalCell, CausalCheck};
|
||||
}
|
||||
|
||||
#[cfg(feature = "sync")]
|
||||
pub(crate) mod future {
|
||||
pub(crate) use crate::sync::AtomicWaker;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::executor::blocking;
|
||||
use crate::runtime::blocking;
|
||||
|
||||
use futures_util::future;
|
||||
use std::io;
|
||||
@@ -143,7 +143,7 @@ pub(crate) mod sealed {
|
||||
//! part of the `ToSocketAddrs` public API. The details will change over
|
||||
//! time.
|
||||
|
||||
use crate::executor::blocking::Blocking;
|
||||
use crate::runtime::blocking::Blocking;
|
||||
|
||||
use futures_core::ready;
|
||||
use std::future::Future;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::loom::sync::atomic::AtomicUsize;
|
||||
use crate::net::driver::platform;
|
||||
use crate::runtime::{Park, Unpark};
|
||||
|
||||
use std::sync::atomic::Ordering::SeqCst;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::executor::blocking::Pool;
|
||||
use crate::loom::thread;
|
||||
use crate::runtime::blocking::Pool;
|
||||
|
||||
use std::usize;
|
||||
|
||||
@@ -262,7 +262,7 @@ impl Drop for PoolWaiter {
|
||||
///
|
||||
/// ```
|
||||
/// # async fn docs() {
|
||||
/// tokio::executor::blocking::in_place(move || {
|
||||
/// tokio::runtime::blocking::in_place(move || {
|
||||
/// // do some compute-heavy work or call synchronous code
|
||||
/// });
|
||||
/// # }
|
||||
@@ -272,9 +272,9 @@ pub fn in_place<F, R>(f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
{
|
||||
use crate::executor;
|
||||
use crate::runtime::{enter, thread_pool};
|
||||
|
||||
executor::enter::exit(|| executor::thread_pool::blocking(f))
|
||||
enter::exit(|| thread_pool::blocking(f))
|
||||
}
|
||||
|
||||
/// Run the provided closure on a thread where blocking is acceptable.
|
||||
@@ -288,7 +288,7 @@ where
|
||||
///
|
||||
/// ```
|
||||
/// # async fn docs() {
|
||||
/// tokio::executor::blocking::run(move || {
|
||||
/// tokio::runtime::blocking::run(move || {
|
||||
/// // do some compute-heavy work or call synchronous code
|
||||
/// }).await;
|
||||
/// # }
|
||||
@@ -1,14 +1,13 @@
|
||||
use crate::executor::blocking::{Pool, PoolWaiter};
|
||||
use crate::executor::current_thread::CurrentThread;
|
||||
#[cfg(feature = "blocking")]
|
||||
use crate::runtime::blocking::{Pool, PoolWaiter};
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
use crate::runtime::current_thread::CurrentThread;
|
||||
#[cfg(feature = "rt-full")]
|
||||
use crate::executor::thread_pool;
|
||||
use crate::net::driver::Reactor;
|
||||
use crate::runtime::{Runtime, Kind};
|
||||
use crate::timer::clock::Clock;
|
||||
use crate::timer::timer::Timer;
|
||||
use crate::runtime::thread_pool;
|
||||
use crate::runtime::{io, timer, Runtime};
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, io};
|
||||
|
||||
/// Builds Tokio Runtime with custom configuration values.
|
||||
///
|
||||
@@ -43,8 +42,8 @@ use std::{fmt, io};
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Builder {
|
||||
/// When `true`, use the current-thread executor.
|
||||
current_thread: bool,
|
||||
/// The task execution model to use.
|
||||
kind: Kind,
|
||||
|
||||
/// The number of worker threads.
|
||||
///
|
||||
@@ -64,7 +63,16 @@ pub struct Builder {
|
||||
before_stop: Option<Arc<dyn Fn() + Send + Sync>>,
|
||||
|
||||
/// The clock to use
|
||||
clock: Clock,
|
||||
clock: timer::Clock,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Kind {
|
||||
Shell,
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
CurrentThread,
|
||||
#[cfg(feature = "rt-full")]
|
||||
ThreadPool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
@@ -74,8 +82,8 @@ impl Builder {
|
||||
/// Configuration methods can be chained on the return value.
|
||||
pub fn new() -> Builder {
|
||||
Builder {
|
||||
// Use the thread-pool executor by default
|
||||
current_thread: false,
|
||||
// No task execution by default
|
||||
kind: Kind::Shell,
|
||||
|
||||
// Default to use an equal number of threads to number of CPU cores
|
||||
num_threads: crate::loom::sys::num_cpus(),
|
||||
@@ -91,7 +99,7 @@ impl Builder {
|
||||
before_stop: None,
|
||||
|
||||
// Default clock
|
||||
clock: Clock::new(),
|
||||
clock: timer::Clock::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,12 +127,20 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Use only the current thread for the runtime.
|
||||
/// Use only the current thread for executing tasks.
|
||||
///
|
||||
/// The network driver, timer, and executor will all be run on the current
|
||||
/// thread during `block_on` calls.
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub fn current_thread(&mut self) -> &mut Self {
|
||||
self.current_thread = true;
|
||||
self.kind = Kind::CurrentThread;
|
||||
self
|
||||
}
|
||||
|
||||
/// Use a thread-pool for executing tasks.
|
||||
#[cfg(feature = "rt-full")]
|
||||
pub fn thread_pool(&mut self) -> &mut Self {
|
||||
self.kind = Kind::ThreadPool;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -224,7 +240,7 @@ impl Builder {
|
||||
}
|
||||
|
||||
/// Set the `Clock` instance that will be used by the runtime.
|
||||
pub fn clock(&mut self, clock: Clock) -> &mut Self {
|
||||
pub fn clock(&mut self, clock: timer::Clock) -> &mut Self {
|
||||
self.clock = clock;
|
||||
self
|
||||
}
|
||||
@@ -245,20 +261,44 @@ impl Builder {
|
||||
/// });
|
||||
/// ```
|
||||
pub fn build(&mut self) -> io::Result<Runtime> {
|
||||
if self.current_thread {
|
||||
self.build_current_thread()
|
||||
} else {
|
||||
self.build_threadpool()
|
||||
match self.kind {
|
||||
Kind::Shell => self.build_shell(),
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
Kind::CurrentThread => self.build_current_thread(),
|
||||
#[cfg(feature = "rt-full")]
|
||||
Kind::ThreadPool => self.build_threadpool(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_current_thread(&mut self) -> io::Result<Runtime> {
|
||||
// Create network driver
|
||||
let net = Reactor::new()?;
|
||||
let net_handles = vec![net.handle()];
|
||||
fn build_shell(&mut self) -> io::Result<Runtime> {
|
||||
use crate::runtime::Kind;
|
||||
|
||||
let timer = Timer::new_with_clock(net, self.clock.clone());
|
||||
let timer_handles = vec![timer.handle()];
|
||||
// Create network driver
|
||||
let (net, handle) = io::create()?;
|
||||
let net_handles = vec![handle];
|
||||
|
||||
let (_timer, handle) = timer::create(net, self.clock.clone());
|
||||
let timer_handles = vec![handle];
|
||||
|
||||
Ok(Runtime {
|
||||
kind: Kind::Shell,
|
||||
net_handles,
|
||||
timer_handles,
|
||||
#[cfg(feature = "blocking")]
|
||||
blocking_pool: PoolWaiter::from(Pool::default()),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
fn build_current_thread(&mut self) -> io::Result<Runtime> {
|
||||
use crate::runtime::Kind;
|
||||
|
||||
// Create network driver
|
||||
let (net, handle) = io::create()?;
|
||||
let net_handles = vec![handle];
|
||||
|
||||
let (timer, handle) = timer::create(net, self.clock.clone());
|
||||
let timer_handles = vec![handle];
|
||||
|
||||
// And now put a single-threaded executor on top of the timer. When
|
||||
// there are no futures ready to do something, it'll let the timer or
|
||||
@@ -277,16 +317,10 @@ impl Builder {
|
||||
})
|
||||
}
|
||||
|
||||
// Without rt-full, the "threadpool" variant just uses current-thread
|
||||
#[cfg(not(feature = "rt-full"))]
|
||||
fn build_threadpool(&mut self) -> io::Result<Runtime> {
|
||||
self.build_current_thread()
|
||||
}
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
fn build_threadpool(&mut self) -> io::Result<Runtime> {
|
||||
use crate::net::driver;
|
||||
use crate::timer::{clock, timer};
|
||||
use crate::runtime::Kind;
|
||||
use crate::timer::clock;
|
||||
use std::sync::Mutex;
|
||||
|
||||
let mut net_handles = Vec::new();
|
||||
@@ -294,13 +328,13 @@ impl Builder {
|
||||
let mut timers = Vec::new();
|
||||
|
||||
for _ in 0..self.num_threads {
|
||||
// Create network driver
|
||||
let net = Reactor::new()?;
|
||||
net_handles.push(net.handle());
|
||||
// Create network driver and handle
|
||||
let (net, handle) = io::create()?;
|
||||
net_handles.push(handle);
|
||||
|
||||
// Create a new timer.
|
||||
let timer = Timer::new_with_clock(net, self.clock.clone());
|
||||
timer_handles.push(timer.handle());
|
||||
let (timer, handle) = timer::create(net, self.clock.clone());
|
||||
timer_handles.push(handle);
|
||||
timers.push(Mutex::new(Some(timer)));
|
||||
}
|
||||
|
||||
@@ -328,7 +362,7 @@ impl Builder {
|
||||
builder
|
||||
.around_worker(move |index, next| {
|
||||
// Configure the network driver
|
||||
let _net = driver::set_default(&net_handles[index]);
|
||||
let _net = io::set_default(&net_handles[index]);
|
||||
|
||||
// Configure the clock
|
||||
clock::with_default(&clock, || {
|
||||
@@ -370,7 +404,7 @@ impl Default for Builder {
|
||||
impl fmt::Debug for Builder {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("Builder")
|
||||
.field("current_thread", &self.current_thread)
|
||||
.field("kind", &self.kind)
|
||||
.field("num_threads", &self.num_threads)
|
||||
.field("thread_name", &self.thread_name)
|
||||
.field("thread_stack_size", &self.thread_stack_size)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::executor::task::{self, JoinHandle, Schedule, Task};
|
||||
use crate::runtime::park::{Park, Unpark};
|
||||
use crate::runtime::task::{self, JoinHandle, Schedule, Task};
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::collections::VecDeque;
|
||||
@@ -130,6 +130,7 @@ where
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
use crate::runtime;
|
||||
use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
use std::task::Poll::Ready;
|
||||
@@ -137,9 +138,9 @@ where
|
||||
let local = &mut self.local;
|
||||
let scheduler = &*self.scheduler;
|
||||
|
||||
crate::executor::global::with_current_thread(scheduler, || {
|
||||
runtime::global::with_current_thread(scheduler, || {
|
||||
let mut _enter =
|
||||
crate::executor::enter().expect("attempting to block while on a Tokio executor");
|
||||
runtime::enter::enter().expect("attempting to block while on a Tokio executor");
|
||||
|
||||
let raw_waker = RawWaker::new(
|
||||
scheduler as *const Scheduler as *const (),
|
||||
@@ -272,7 +273,7 @@ impl Schedule for Scheduler {
|
||||
}
|
||||
|
||||
fn schedule(&self, task: Task<Self>) {
|
||||
use crate::executor::global;
|
||||
use crate::runtime::global;
|
||||
|
||||
if global::current_thread_is_current(self) {
|
||||
unsafe { self.schedule_local(task) };
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
#[cfg(feature = "rt-full")]
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@@ -101,14 +100,13 @@ pub(crate) fn exit<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
impl Enter {
|
||||
/// Blocks the thread on the specified future, returning the value with
|
||||
/// which that future completes.
|
||||
#[cfg(feature = "rt-full")]
|
||||
pub(crate) fn block_on<F: Future>(&mut self, mut f: F) -> F::Output {
|
||||
use crate::executor::park::{Park, ParkThread};
|
||||
use crate::runtime::park::{CachedParkThread, Park};
|
||||
use std::pin::Pin;
|
||||
use std::task::Context;
|
||||
use std::task::Poll::Ready;
|
||||
|
||||
let mut park = ParkThread::new();
|
||||
let mut park = CachedParkThread::new();
|
||||
let waker = park.unpark().into_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
use crate::executor::current_thread;
|
||||
use crate::runtime::current_thread;
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
use crate::executor::thread_pool;
|
||||
use crate::runtime::thread_pool;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::future::Future;
|
||||
@@ -0,0 +1,56 @@
|
||||
pub(crate) use self::variant::*;
|
||||
|
||||
/// Re-exported for convenience.
|
||||
pub(crate) use std::io::Result;
|
||||
|
||||
#[cfg(feature = "net-driver")]
|
||||
mod variant {
|
||||
use crate::net::driver;
|
||||
|
||||
use std::io;
|
||||
|
||||
/// The driver value the runtime passes to the `timer` layer.
|
||||
///
|
||||
/// When the `io-driver` feature is enabled, this is the "real" I/O driver
|
||||
/// backed by Mio. Without the `io-driver` feature, this is a thread parker
|
||||
/// backed by a condition variable.
|
||||
pub(crate) type Driver = driver::Reactor;
|
||||
|
||||
/// The handle the runtime stores for future use.
|
||||
///
|
||||
/// When the `io-driver` feature is **not** enabled, this is `()`.
|
||||
pub(crate) type Handle = driver::Handle;
|
||||
|
||||
pub(crate) fn create() -> io::Result<(Driver, Handle)> {
|
||||
let driver = driver::Reactor::new()?;
|
||||
let handle = driver.handle();
|
||||
|
||||
Ok((driver, handle))
|
||||
}
|
||||
|
||||
pub(crate) fn set_default(handle: &Handle) -> driver::DefaultGuard<'_> {
|
||||
driver::set_default(handle)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "net-driver"))]
|
||||
mod variant {
|
||||
use crate::runtime::park::ParkThread;
|
||||
|
||||
use std::io;
|
||||
|
||||
/// I/O is not enabled, use a condition variable based parker
|
||||
pub(crate) type Driver = ParkThread;
|
||||
|
||||
/// There is no handle
|
||||
pub(crate) type Handle = ();
|
||||
|
||||
pub(crate) fn create() -> io::Result<(Driver, Handle)> {
|
||||
let driver = ParkThread::new();
|
||||
|
||||
Ok((driver, ()))
|
||||
}
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) fn set_default(_handle: &Handle) {}
|
||||
}
|
||||
+78
-18
@@ -128,24 +128,57 @@
|
||||
//! [`tokio::spawn`]: ../executor/fn.spawn.html
|
||||
//! [`tokio::main`]: ../../tokio_macros/attr.main.html
|
||||
|
||||
// At the top due to macros
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod tests;
|
||||
|
||||
#[cfg(all(not(feature = "blocking"), feature = "rt-full"))]
|
||||
mod blocking;
|
||||
#[cfg(feature = "blocking")]
|
||||
pub mod blocking;
|
||||
|
||||
mod builder;
|
||||
pub use self::builder::Builder;
|
||||
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
mod current_thread;
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
mod enter;
|
||||
|
||||
mod global;
|
||||
pub use self::global::spawn;
|
||||
|
||||
mod io;
|
||||
|
||||
mod park;
|
||||
pub use self::park::{Park, Unpark};
|
||||
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
mod spawner;
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub use self::spawner::Spawner;
|
||||
|
||||
#[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411
|
||||
pub use crate::executor::{JoinError, JoinHandle};
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
mod task;
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub use self::task::{JoinError, JoinHandle};
|
||||
|
||||
mod timer;
|
||||
|
||||
use crate::executor::blocking::{self, PoolWaiter};
|
||||
use crate::executor::current_thread::CurrentThread;
|
||||
#[cfg(feature = "rt-full")]
|
||||
use crate::executor::thread_pool::ThreadPool;
|
||||
use crate::net::{self, driver};
|
||||
use crate::timer::timer;
|
||||
pub(crate) mod thread_pool;
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
use crate::runtime::blocking::PoolWaiter;
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
use crate::runtime::current_thread::CurrentThread;
|
||||
#[cfg(feature = "rt-full")]
|
||||
use crate::runtime::thread_pool::ThreadPool;
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
|
||||
/// The Tokio runtime, includes a reactor as well as an executor for running
|
||||
/// tasks.
|
||||
@@ -178,21 +211,30 @@ pub struct Runtime {
|
||||
kind: Kind,
|
||||
|
||||
/// Handles to the network drivers
|
||||
net_handles: Vec<net::driver::Handle>,
|
||||
net_handles: Vec<io::Handle>,
|
||||
|
||||
/// Timer handles
|
||||
timer_handles: Vec<timer::Handle>,
|
||||
|
||||
/// Blocking pool handle
|
||||
#[cfg(feature = "blocking")]
|
||||
blocking_pool: PoolWaiter,
|
||||
}
|
||||
|
||||
/// The runtime executor is either a thread-pool or a current-thread executor.
|
||||
#[derive(Debug)]
|
||||
enum Kind {
|
||||
/// Not able to execute concurrent tasks. This variant is mostly used to get
|
||||
/// access to the driver handles.
|
||||
Shell,
|
||||
|
||||
/// Execute all tasks on the current-thread.
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
CurrentThread(CurrentThread<timer::Driver>),
|
||||
|
||||
/// Execute tasks across multiple threads.
|
||||
#[cfg(feature = "rt-full")]
|
||||
ThreadPool(ThreadPool),
|
||||
CurrentThread(CurrentThread<timer::Timer<net::driver::Reactor>>),
|
||||
}
|
||||
|
||||
impl Runtime {
|
||||
@@ -222,7 +264,16 @@ impl Runtime {
|
||||
///
|
||||
/// [mod]: index.html
|
||||
pub fn new() -> io::Result<Self> {
|
||||
Builder::new().build()
|
||||
#[cfg(feature = "rt-full")]
|
||||
let ret = Builder::new().thread_pool().build();
|
||||
|
||||
#[cfg(all(not(feature = "rt-full"), feature = "rt-current-thread"))]
|
||||
let ret = Builder::new().current_thread().build();
|
||||
|
||||
#[cfg(not(feature = "rt-current-thread"))]
|
||||
let ret = Builder::new().build();
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
/// Spawn a future onto the Tokio runtime.
|
||||
@@ -255,11 +306,13 @@ impl Runtime {
|
||||
///
|
||||
/// This function panics if the spawn fails. Failure occurs if the executor
|
||||
/// is currently at capacity and is unable to spawn a new future.
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
F: Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
match &self.kind {
|
||||
Kind::Shell => panic!("task execution disabled"),
|
||||
#[cfg(feature = "rt-full")]
|
||||
Kind::ThreadPool(exec) => exec.spawn(future),
|
||||
Kind::CurrentThread(exec) => exec.spawn(future),
|
||||
@@ -279,18 +332,22 @@ impl Runtime {
|
||||
///
|
||||
/// This function panics if the executor is at capacity, if the provided
|
||||
/// future panics, or if called within an asynchronous execution context.
|
||||
#[cfg(feature = "blocking")] // TODO: remove this
|
||||
pub fn block_on<F: Future>(&mut self, future: F) -> F::Output {
|
||||
let _net = driver::set_default(&self.net_handles[0]);
|
||||
let _net = io::set_default(&self.net_handles[0]);
|
||||
let _timer = timer::set_default(&self.timer_handles[0]);
|
||||
|
||||
let kind = &mut self.kind;
|
||||
|
||||
blocking::with_pool(&self.blocking_pool, || {
|
||||
match kind {
|
||||
#[cfg(feature = "rt-full")]
|
||||
Kind::ThreadPool(exec) => exec.block_on(future),
|
||||
Kind::CurrentThread(exec) => exec.block_on(future),
|
||||
blocking::with_pool(&self.blocking_pool, || match kind {
|
||||
Kind::Shell => {
|
||||
let mut enter = enter::enter().unwrap();
|
||||
enter.block_on(future)
|
||||
}
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
Kind::CurrentThread(exec) => exec.block_on(future),
|
||||
#[cfg(feature = "rt-full")]
|
||||
Kind::ThreadPool(exec) => exec.block_on(future),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -310,11 +367,14 @@ impl Runtime {
|
||||
///
|
||||
/// spawner.spawn(async { println!("hello"); });
|
||||
/// ```
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
pub fn spawner(&self) -> Spawner {
|
||||
match &self.kind {
|
||||
Kind::Shell => Spawner::shell(),
|
||||
#[cfg(feature = "rt-current-thread")]
|
||||
Kind::CurrentThread(exec) => Spawner::current_thread(exec.spawner()),
|
||||
#[cfg(feature = "rt-full")]
|
||||
Kind::ThreadPool(exec) => Spawner::thread_pool(exec.spawner().clone()),
|
||||
Kind::CurrentThread(exec) => Spawner::current_thread(exec.spawner()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,10 @@
|
||||
//! [up]: trait.Unpark.html
|
||||
//! [mio]: https://docs.rs/mio/0.6/mio/struct.Poll.html
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
mod thread;
|
||||
#[cfg(feature = "rt-full")]
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) use self::thread::CachedParkThread;
|
||||
#[cfg(not(feature = "net-driver"))]
|
||||
pub(crate) use self::thread::ParkThread;
|
||||
|
||||
use std::sync::Arc;
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::loom::sync::atomic::AtomicUsize;
|
||||
use crate::loom::sync::{Arc, Condvar, Mutex};
|
||||
use crate::runtime::park::{Park, Unpark};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
@@ -18,10 +18,14 @@ use std::time::Duration;
|
||||
/// means that an instance of `ParkThread` might be unblocked by a handle
|
||||
/// associated with a different `ParkThread` instance.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ParkThread {
|
||||
pub(crate) struct CachedParkThread {
|
||||
_anchor: PhantomData<Rc<()>>,
|
||||
}
|
||||
|
||||
pub(crate) struct ParkThread {
|
||||
inner: Arc<Inner>,
|
||||
}
|
||||
|
||||
/// Error returned by [`ParkThread`]
|
||||
///
|
||||
/// This currently is never returned, but might at some point in the future.
|
||||
@@ -32,10 +36,6 @@ pub(crate) struct ParkError {
|
||||
_p: (),
|
||||
}
|
||||
|
||||
struct Parker {
|
||||
unparker: Arc<Inner>,
|
||||
}
|
||||
|
||||
/// Unblocks a thread that was blocked by `ParkThread`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct UnparkThread {
|
||||
@@ -54,32 +54,38 @@ const NOTIFY: usize = 1;
|
||||
const SLEEP: usize = 2;
|
||||
|
||||
thread_local! {
|
||||
static CURRENT_PARKER: Parker = Parker::new();
|
||||
static CURRENT_PARKER: ParkThread = ParkThread::new();
|
||||
}
|
||||
|
||||
// ==== impl Parker ====
|
||||
// ==== impl ParkThread ====
|
||||
|
||||
impl Parker {
|
||||
fn new() -> Self {
|
||||
impl ParkThread {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
unparker: Arc::new(Inner {
|
||||
inner: Arc::new(Inner {
|
||||
state: AtomicUsize::new(IDLE),
|
||||
mutex: Mutex::new(()),
|
||||
condvar: Condvar::new(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unparker(&self) -> &Arc<Inner> {
|
||||
&self.unparker
|
||||
impl Park for ParkThread {
|
||||
type Unpark = UnparkThread;
|
||||
type Error = ParkError;
|
||||
|
||||
fn unpark(&self) -> Self::Unpark {
|
||||
let inner = self.inner.clone();
|
||||
UnparkThread { inner }
|
||||
}
|
||||
|
||||
fn park(&self) -> Result<(), ParkError> {
|
||||
self.unparker.park(None)
|
||||
fn park(&mut self) -> Result<(), Self::Error> {
|
||||
self.inner.park(None)
|
||||
}
|
||||
|
||||
fn park_timeout(&self, timeout: Duration) -> Result<(), ParkError> {
|
||||
self.unparker.park(Some(timeout))
|
||||
fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
|
||||
self.inner.park(Some(duration))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,13 +162,14 @@ impl Inner {
|
||||
|
||||
// ===== impl ParkThread =====
|
||||
|
||||
impl ParkThread {
|
||||
impl CachedParkThread {
|
||||
/// Create a new `ParkThread` handle for the current thread.
|
||||
///
|
||||
/// This type cannot be moved to other threads, so it should be created on
|
||||
/// the thread that the caller intends to park.
|
||||
pub(crate) fn new() -> ParkThread {
|
||||
ParkThread {
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) fn new() -> CachedParkThread {
|
||||
CachedParkThread {
|
||||
_anchor: PhantomData,
|
||||
}
|
||||
}
|
||||
@@ -170,28 +177,27 @@ impl ParkThread {
|
||||
/// Get a reference to the `ParkThread` handle for this thread.
|
||||
fn with_current<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&Parker) -> R,
|
||||
F: FnOnce(&ParkThread) -> R,
|
||||
{
|
||||
CURRENT_PARKER.with(|inner| f(inner))
|
||||
}
|
||||
}
|
||||
|
||||
impl Park for ParkThread {
|
||||
impl Park for CachedParkThread {
|
||||
type Unpark = UnparkThread;
|
||||
type Error = ParkError;
|
||||
|
||||
fn unpark(&self) -> Self::Unpark {
|
||||
let inner = self.with_current(|inner| inner.unparker().clone());
|
||||
UnparkThread { inner }
|
||||
self.with_current(|park_thread| park_thread.unpark())
|
||||
}
|
||||
|
||||
fn park(&mut self) -> Result<(), Self::Error> {
|
||||
self.with_current(|inner| inner.park())?;
|
||||
self.with_current(|park_thread| park_thread.inner.park(None))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
|
||||
self.with_current(|inner| inner.park_timeout(duration))?;
|
||||
self.with_current(|park_thread| park_thread.inner.park(Some(duration)))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -210,7 +216,7 @@ impl Unpark for UnparkThread {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
#[cfg(feature = "blocking")]
|
||||
mod waker {
|
||||
use super::{Inner, UnparkThread};
|
||||
use crate::loom::sync::Arc;
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::executor::current_thread;
|
||||
use crate::runtime::current_thread;
|
||||
#[cfg(feature = "rt-full")]
|
||||
use crate::executor::thread_pool;
|
||||
use crate::runtime::thread_pool;
|
||||
use crate::runtime::JoinHandle;
|
||||
|
||||
use std::future::Future;
|
||||
@@ -13,24 +13,33 @@ use std::future::Future;
|
||||
/// For more details, see the [module level](index.html) documentation.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Spawner {
|
||||
kind: Kind
|
||||
kind: Kind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Kind {
|
||||
Shell,
|
||||
#[cfg(feature = "rt-full")]
|
||||
ThreadPool(thread_pool::Spawner),
|
||||
CurrentThread(current_thread::Spawner),
|
||||
}
|
||||
|
||||
impl Spawner {
|
||||
pub(super) fn shell() -> Spawner {
|
||||
Spawner { kind: Kind::Shell }
|
||||
}
|
||||
|
||||
#[cfg(feature = "rt-full")]
|
||||
pub(super) fn thread_pool(spawner: thread_pool::Spawner) -> Spawner {
|
||||
Spawner { kind: Kind::ThreadPool(spawner) }
|
||||
Spawner {
|
||||
kind: Kind::ThreadPool(spawner),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn current_thread(spawner: current_thread::Spawner) -> Spawner {
|
||||
Spawner { kind: Kind::CurrentThread(spawner) }
|
||||
Spawner {
|
||||
kind: Kind::CurrentThread(spawner),
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn a future onto the Tokio runtime.
|
||||
@@ -69,6 +78,7 @@ impl Spawner {
|
||||
F: Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
match &self.kind {
|
||||
Kind::Shell => panic!("spawning not enabled for runtime"),
|
||||
#[cfg(feature = "rt-full")]
|
||||
Kind::ThreadPool(spawner) => spawner.spawn(future),
|
||||
Kind::CurrentThread(spawner) => spawner.spawn(future),
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use crate::executor::task::raw::{self, Vtable};
|
||||
use crate::executor::task::state::State;
|
||||
use crate::executor::task::waker::waker_ref;
|
||||
use crate::executor::task::Schedule;
|
||||
use crate::loom::alloc::Track;
|
||||
use crate::loom::cell::CausalCell;
|
||||
use crate::runtime::task::raw::{self, Vtable};
|
||||
use crate::runtime::task::state::State;
|
||||
use crate::runtime::task::waker::waker_ref;
|
||||
use crate::runtime::task::Schedule;
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::future::Future;
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::executor::task::core::{Cell, Core, Header, Trailer};
|
||||
use crate::executor::task::state::Snapshot;
|
||||
use crate::executor::task::{JoinError, Schedule, Task};
|
||||
use crate::loom::alloc::Track;
|
||||
use crate::loom::cell::CausalCheck;
|
||||
use crate::runtime::task::core::{Cell, Core, Header, Trailer};
|
||||
use crate::runtime::task::state::Snapshot;
|
||||
use crate::runtime::task::{JoinError, Schedule, Task};
|
||||
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::executor::task::raw::RawTask;
|
||||
use crate::loom::alloc::Track;
|
||||
use crate::runtime::task::RawTask;
|
||||
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::executor::task::{Header, Task};
|
||||
use crate::runtime::task::{Header, Task};
|
||||
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
@@ -1,4 +1,5 @@
|
||||
mod core;
|
||||
use self::core::Cell;
|
||||
pub(crate) use self::core::Header;
|
||||
|
||||
mod error;
|
||||
@@ -6,6 +7,7 @@ mod error;
|
||||
pub use self::error::JoinError;
|
||||
|
||||
mod harness;
|
||||
use self::harness::Harness;
|
||||
|
||||
mod join;
|
||||
#[cfg(any(feature = "rt-current-thread", feature = "rt-full"))]
|
||||
@@ -16,19 +18,20 @@ mod list;
|
||||
pub(crate) use self::list::OwnedList;
|
||||
|
||||
mod raw;
|
||||
use self::raw::RawTask;
|
||||
|
||||
mod stack;
|
||||
pub(crate) use self::stack::TransferStack;
|
||||
|
||||
mod state;
|
||||
use self::state::{Snapshot, State};
|
||||
|
||||
mod waker;
|
||||
|
||||
/// Unit tests
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use self::raw::RawTask;
|
||||
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr::NonNull;
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::executor::task::core::Cell;
|
||||
use crate::executor::task::harness::Harness;
|
||||
use crate::executor::task::state::{Snapshot, State};
|
||||
use crate::executor::task::{Header, Schedule};
|
||||
use crate::loom::alloc::Track;
|
||||
use crate::runtime::task::Cell;
|
||||
use crate::runtime::task::Harness;
|
||||
use crate::runtime::task::{Header, Schedule};
|
||||
use crate::runtime::task::{Snapshot, State};
|
||||
|
||||
use std::future::Future;
|
||||
use std::ptr::NonNull;
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::executor::task::{Header, Task};
|
||||
use crate::loom::sync::atomic::AtomicPtr;
|
||||
use crate::runtime::task::{Header, Task};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr::{self, NonNull};
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::executor::task;
|
||||
use crate::executor::tests::loom_schedule::LoomSchedule;
|
||||
use crate::runtime::task;
|
||||
use crate::runtime::tests::loom_schedule::LoomSchedule;
|
||||
|
||||
use tokio_test::{assert_err, assert_ok};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::executor::task::{self, Header};
|
||||
use crate::executor::tests::backoff::*;
|
||||
use crate::executor::tests::mock_schedule::{mock, Mock};
|
||||
use crate::executor::tests::track_drop::track_drop;
|
||||
use crate::runtime::task::{self, Header};
|
||||
use crate::runtime::tests::backoff::*;
|
||||
use crate::runtime::tests::mock_schedule::{mock, Mock};
|
||||
use crate::runtime::tests::track_drop::track_drop;
|
||||
use crate::sync::oneshot;
|
||||
|
||||
use tokio_test::task::spawn;
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::executor::task::harness::Harness;
|
||||
use crate::executor::task::{Header, Schedule};
|
||||
use crate::runtime::task::harness::Harness;
|
||||
use crate::runtime::task::{Header, Schedule};
|
||||
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
use crate::executor::task::{Schedule, Task};
|
||||
use crate::runtime::task::{Schedule, Task};
|
||||
|
||||
use loom::sync::Notify;
|
||||
use std::collections::VecDeque;
|
||||
@@ -1,6 +1,6 @@
|
||||
#![allow(warnings)]
|
||||
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::runtime::{Park, Unpark};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#![allow(warnings)]
|
||||
|
||||
use crate::executor::task::{Header, Schedule, Task};
|
||||
use crate::runtime::task::{Header, Schedule, Task};
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Mutex;
|
||||
+8
-6
@@ -1,7 +1,7 @@
|
||||
use crate::executor::park::Park;
|
||||
use crate::executor::thread_pool::{shutdown, worker, worker::Worker, Spawner, ThreadPool};
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::loom::sys::num_cpus;
|
||||
use crate::runtime::park::Park;
|
||||
use crate::runtime::thread_pool::{shutdown, Spawner, ThreadPool, Worker};
|
||||
|
||||
use std::{fmt, usize};
|
||||
|
||||
@@ -90,6 +90,8 @@ impl Builder {
|
||||
F: FnMut(usize) -> P,
|
||||
P: Park + Send + 'static,
|
||||
{
|
||||
use crate::runtime::thread_pool::worker;
|
||||
|
||||
let (shutdown_tx, shutdown_rx) = shutdown::channel();
|
||||
|
||||
let around_worker = self.around_worker.as_ref().map(Arc::clone);
|
||||
@@ -134,7 +136,7 @@ impl Builder {
|
||||
})
|
||||
as Box<dyn Fn(Worker<BoxedPark<P>>) -> Box<dyn FnOnce() + Send> + Send + Sync>);
|
||||
|
||||
let mut blocking = crate::executor::blocking::Builder::default();
|
||||
let mut blocking = crate::runtime::blocking::Builder::default();
|
||||
blocking.name(self.name.clone());
|
||||
if let Some(ss) = self.stack_size {
|
||||
blocking.stack_size(ss);
|
||||
@@ -150,11 +152,11 @@ impl Builder {
|
||||
|
||||
// Spawn threads for each worker
|
||||
for worker in workers {
|
||||
crate::executor::blocking::Pool::spawn(&blocking, launch_worker(worker))
|
||||
crate::runtime::blocking::Pool::spawn(&blocking, launch_worker(worker))
|
||||
}
|
||||
|
||||
let spawner = Spawner::new(pool);
|
||||
let blocking = crate::executor::blocking::PoolWaiter::from(blocking);
|
||||
let blocking = crate::runtime::blocking::PoolWaiter::from(blocking);
|
||||
ThreadPool::from_parts(spawner, shutdown_rx, blocking)
|
||||
}
|
||||
}
|
||||
@@ -189,7 +191,7 @@ impl<P> Park for BoxedPark<P>
|
||||
where
|
||||
P: Park,
|
||||
{
|
||||
type Unpark = Box<dyn crate::executor::park::Unpark>;
|
||||
type Unpark = Box<dyn crate::runtime::park::Unpark>;
|
||||
type Error = P::Error;
|
||||
|
||||
fn unpark(&self) -> Self::Unpark {
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
use crate::executor::park::Unpark;
|
||||
use crate::executor::thread_pool::{worker, Owned};
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::runtime::park::Unpark;
|
||||
use crate::runtime::thread_pool::{worker, Owned};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
@@ -27,6 +27,8 @@ use self::shared::Shared;
|
||||
mod shutdown;
|
||||
|
||||
mod worker;
|
||||
use self::worker::Worker;
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) use worker::blocking;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::executor::task::{self, Task};
|
||||
use crate::executor::thread_pool::{queue, Shared};
|
||||
use crate::executor::util::FastRand;
|
||||
use crate::runtime::task::{self, Task};
|
||||
use crate::runtime::thread_pool::{queue, Shared};
|
||||
use crate::util::FastRand;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::executor::blocking::PoolWaiter;
|
||||
use crate::executor::task::JoinHandle;
|
||||
use crate::executor::thread_pool::{shutdown, Spawner};
|
||||
use crate::runtime::blocking::PoolWaiter;
|
||||
use crate::runtime::task::JoinHandle;
|
||||
use crate::runtime::thread_pool::{shutdown, Spawner};
|
||||
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
@@ -54,10 +54,10 @@ impl ThreadPool {
|
||||
where
|
||||
F: Future,
|
||||
{
|
||||
crate::executor::global::with_thread_pool(self.spawner(), || {
|
||||
let mut enter =
|
||||
crate::executor::enter().expect("attempting to block while on a Tokio executor");
|
||||
crate::executor::blocking::with_pool(self.spawner.blocking_pool(), || {
|
||||
crate::runtime::global::with_thread_pool(self.spawner(), || {
|
||||
let mut enter = crate::runtime::enter::enter()
|
||||
.expect("attempting to block while on a Tokio executor");
|
||||
crate::runtime::blocking::with_pool(self.spawner.blocking_pool(), || {
|
||||
enter.block_on(future)
|
||||
})
|
||||
})
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
use crate::executor::task::{Header, Task};
|
||||
use crate::loom::sync::atomic::AtomicUsize;
|
||||
use crate::loom::sync::Mutex;
|
||||
use crate::runtime::task::{Header, Task};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr::{self, NonNull};
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
use crate::executor::task::Task;
|
||||
use crate::executor::thread_pool::queue::Cluster;
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::runtime::task::Task;
|
||||
use crate::runtime::thread_pool::queue::Cluster;
|
||||
|
||||
pub(crate) struct Inject<T: 'static> {
|
||||
cluster: Arc<Cluster<T>>,
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
use crate::executor::task::Task;
|
||||
use crate::executor::thread_pool::queue::global;
|
||||
use crate::executor::thread_pool::LOCAL_QUEUE_CAPACITY;
|
||||
use crate::loom::cell::{CausalCell, CausalCheck};
|
||||
use crate::loom::sync::atomic::{self, AtomicU32};
|
||||
use crate::runtime::task::Task;
|
||||
use crate::runtime::thread_pool::queue::global;
|
||||
use crate::runtime::thread_pool::LOCAL_QUEUE_CAPACITY;
|
||||
|
||||
use std::fmt;
|
||||
use std::mem::MaybeUninit;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
use crate::executor::task::Task;
|
||||
use crate::executor::thread_pool::queue::{local, Cluster, Inject};
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::runtime::task::Task;
|
||||
use crate::runtime::thread_pool::queue::{local, Cluster, Inject};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
@@ -2,12 +2,12 @@
|
||||
//!
|
||||
//! - Attempt to spin.
|
||||
|
||||
use crate::executor::park::Unpark;
|
||||
use crate::executor::task::{self, JoinHandle, Task};
|
||||
use crate::executor::thread_pool::{current, queue, Idle, Owned, Shared};
|
||||
use crate::executor::util::{CachePadded, FastRand};
|
||||
use crate::loom::rand::seed;
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::runtime::park::Unpark;
|
||||
use crate::runtime::task::{self, JoinHandle, Task};
|
||||
use crate::runtime::thread_pool::{current, queue, Idle, Owned, Shared};
|
||||
use crate::util::{CachePadded, FastRand};
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::future::Future;
|
||||
@@ -29,7 +29,7 @@ where
|
||||
idle: Idle,
|
||||
|
||||
/// Pool where blocking tasks should be spawned.
|
||||
pub(crate) blocking: Arc<crate::executor::blocking::Pool>,
|
||||
pub(crate) blocking: Arc<crate::runtime::blocking::Pool>,
|
||||
}
|
||||
|
||||
unsafe impl<P: Unpark> Send for Set<P> {}
|
||||
@@ -43,7 +43,7 @@ where
|
||||
pub(crate) fn new<F>(
|
||||
num_workers: usize,
|
||||
mut mk_unpark: F,
|
||||
blocking: Arc<crate::executor::blocking::Pool>,
|
||||
blocking: Arc<crate::runtime::blocking::Pool>,
|
||||
) -> Self
|
||||
where
|
||||
F: FnMut(usize) -> P,
|
||||
@@ -112,7 +112,7 @@ where
|
||||
self.schedule(task);
|
||||
}
|
||||
|
||||
pub(super) fn blocking_pool(&self) -> &Arc<crate::executor::blocking::Pool> {
|
||||
pub(super) fn blocking_pool(&self) -> &Arc<crate::runtime::blocking::Pool> {
|
||||
&self.blocking
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::executor::park::Unpark;
|
||||
use crate::executor::task::{self, Schedule, Task};
|
||||
use crate::executor::thread_pool::worker;
|
||||
use crate::runtime::park::Unpark;
|
||||
use crate::runtime::task::{self, Schedule, Task};
|
||||
use crate::runtime::thread_pool::worker;
|
||||
|
||||
use std::ptr;
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ pub(super) fn channel() -> (Sender, Receiver) {
|
||||
impl Receiver {
|
||||
/// Block the current thread until all `Sender` handles drop.
|
||||
pub(crate) fn wait(&mut self) {
|
||||
use crate::executor::enter;
|
||||
use crate::runtime::enter::enter;
|
||||
|
||||
let mut e = match enter() {
|
||||
Ok(e) => e,
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
use crate::executor::park::Unpark;
|
||||
use crate::executor::task::JoinHandle;
|
||||
use crate::executor::thread_pool::worker;
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::runtime::park::Unpark;
|
||||
use crate::runtime::task::JoinHandle;
|
||||
use crate::runtime::thread_pool::worker;
|
||||
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
@@ -45,7 +45,7 @@ impl Spawner {
|
||||
self.workers.spawn_background(future);
|
||||
}
|
||||
|
||||
pub(super) fn blocking_pool(&self) -> &Arc<crate::executor::blocking::Pool> {
|
||||
pub(super) fn blocking_pool(&self) -> &Arc<crate::runtime::blocking::Pool> {
|
||||
self.workers.blocking_pool()
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::executor::tests::loom_oneshot as oneshot;
|
||||
use crate::executor::thread_pool::{self, Builder};
|
||||
use crate::runtime::tests::loom_oneshot as oneshot;
|
||||
use crate::runtime::thread_pool::{self, Builder};
|
||||
use crate::runtime::{Park, Unpark};
|
||||
use crate::spawn;
|
||||
|
||||
use loom::sync::atomic::{AtomicBool, AtomicUsize};
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
use crate::executor::task::{self, Task};
|
||||
use crate::executor::tests::mock_schedule::{Noop, NOOP_SCHEDULE};
|
||||
use crate::executor::thread_pool::queue;
|
||||
use crate::runtime::task::{self, Task};
|
||||
use crate::runtime::tests::mock_schedule::{Noop, NOOP_SCHEDULE};
|
||||
use crate::runtime::thread_pool::queue;
|
||||
|
||||
use loom::thread;
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::executor::thread_pool;
|
||||
use crate::runtime::{thread_pool, Park, Unpark};
|
||||
|
||||
use futures_util::future::poll_fn;
|
||||
use std::future::Future;
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
use crate::executor::task::{self, Task};
|
||||
use crate::executor::tests::mock_schedule::{Noop, NOOP_SCHEDULE};
|
||||
use crate::executor::thread_pool::{queue, LOCAL_QUEUE_CAPACITY};
|
||||
use crate::runtime::task::{self, Task};
|
||||
use crate::runtime::tests::mock_schedule::{Noop, NOOP_SCHEDULE};
|
||||
use crate::runtime::thread_pool::{queue, LOCAL_QUEUE_CAPACITY};
|
||||
|
||||
macro_rules! assert_pop {
|
||||
($q:expr, $expect:expr) => {
|
||||
+4
-4
@@ -1,5 +1,5 @@
|
||||
use crate::executor::tests::track_drop::track_drop;
|
||||
use crate::executor::thread_pool;
|
||||
use crate::runtime::tests::track_drop::track_drop;
|
||||
use crate::runtime::thread_pool;
|
||||
|
||||
use tokio_test::assert_ok;
|
||||
|
||||
@@ -11,8 +11,8 @@ macro_rules! pool {
|
||||
(pool, w.remove(0), w.remove(0), mock_park)
|
||||
}};
|
||||
(! $n:expr) => {{
|
||||
let mut mock_park = crate::executor::tests::mock_park::MockPark::new();
|
||||
let blocking = std::sync::Arc::new(crate::executor::blocking::Pool::default());
|
||||
let mut mock_park = crate::runtime::tests::mock_park::MockPark::new();
|
||||
let blocking = std::sync::Arc::new(crate::runtime::blocking::Pool::default());
|
||||
let (pool, workers) = thread_pool::worker::create_set(
|
||||
$n,
|
||||
|index| Box::new(mock_park.mk_park(index)),
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::executor::task::Task;
|
||||
use crate::executor::thread_pool::{current, Owned, Shared, Spawner};
|
||||
use crate::loom::sync::Arc;
|
||||
use crate::runtime::park::{Park, Unpark};
|
||||
use crate::runtime::task::Task;
|
||||
use crate::runtime::thread_pool::{current, Owned, Shared, Spawner};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -38,7 +38,7 @@ where
|
||||
}
|
||||
|
||||
// TODO: remove this re-export
|
||||
pub(super) use crate::executor::thread_pool::set::Set;
|
||||
pub(super) use crate::runtime::thread_pool::set::Set;
|
||||
|
||||
pub(crate) struct Worker<P: Park + 'static> {
|
||||
/// Entry in the set of workers.
|
||||
@@ -58,7 +58,7 @@ pub(super) fn create_set<F, P>(
|
||||
pool_size: usize,
|
||||
mk_park: F,
|
||||
launch_worker: LaunchWorker<P>,
|
||||
blocking: Arc<crate::executor::blocking::Pool>,
|
||||
blocking: Arc<crate::runtime::blocking::Pool>,
|
||||
) -> (Arc<Set<P::Unpark>>, Vec<Worker<P>>)
|
||||
where
|
||||
P: Send + Park,
|
||||
@@ -131,10 +131,11 @@ where
|
||||
|
||||
// Track the current worker
|
||||
current::set(&pool, index, || {
|
||||
let _enter = crate::executor::enter().expect("executor already running on thread");
|
||||
let _enter =
|
||||
crate::runtime::enter::enter().expect("executor already running on thread");
|
||||
|
||||
crate::executor::global::with_thread_pool(&spawner, || {
|
||||
crate::executor::blocking::with_pool(blocking, || {
|
||||
crate::runtime::global::with_thread_pool(&spawner, || {
|
||||
crate::runtime::blocking::with_pool(blocking, || {
|
||||
ON_BLOCK.with(|ob| {
|
||||
// Ensure that the ON_BLOCK is removed from the thread-local context
|
||||
// when leaving the scope. This handles cases that involve panicking.
|
||||
@@ -220,7 +221,7 @@ where
|
||||
// instances of the Worker, and compare_exchange it to true afterwards
|
||||
// in an attempt to take it back. if it succeeds, we just resume where
|
||||
// we were. if it fails, another thread has already stolen the Worker.
|
||||
crate::executor::blocking::Pool::spawn(
|
||||
crate::runtime::blocking::Pool::spawn(
|
||||
&pool.blocking,
|
||||
launch_worker(worker),
|
||||
);
|
||||
@@ -0,0 +1,41 @@
|
||||
pub(crate) use self::variant::*;
|
||||
|
||||
#[cfg(feature = "timer")]
|
||||
mod variant {
|
||||
use crate::runtime::io;
|
||||
use crate::timer::{clock, timer};
|
||||
|
||||
pub(crate) type Clock = clock::Clock;
|
||||
pub(crate) type Driver = timer::Timer<io::Driver>;
|
||||
pub(crate) type Handle = timer::Handle;
|
||||
|
||||
/// Create a new timer driver / handle pair
|
||||
pub(crate) fn create(io_driver: io::Driver, clock: Clock) -> (Driver, Handle) {
|
||||
let driver = timer::Timer::new_with_clock(io_driver, clock);
|
||||
let handle = driver.handle();
|
||||
|
||||
(driver, handle)
|
||||
}
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) fn set_default(handle: &Handle) -> timer::DefaultGuard<'_> {
|
||||
timer::set_default(handle)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "timer"))]
|
||||
mod variant {
|
||||
use crate::runtime::io;
|
||||
|
||||
pub(crate) type Clock = ();
|
||||
pub(crate) type Driver = io::Driver;
|
||||
pub(crate) type Handle = ();
|
||||
|
||||
/// Create a new timer driver / handle pair
|
||||
pub(crate) fn create(io_driver: io::Driver, _clock: Clock) -> (Driver, Handle) {
|
||||
(io_driver, ())
|
||||
}
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) fn set_default(_handle: &Handle) {}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ use self::entry::Entry;
|
||||
|
||||
mod handle;
|
||||
pub(crate) use self::handle::HandlePriv;
|
||||
pub use self::handle::{set_default, Handle};
|
||||
pub use self::handle::{set_default, DefaultGuard, Handle};
|
||||
|
||||
mod registration;
|
||||
pub(crate) use self::registration::Registration;
|
||||
@@ -41,7 +41,7 @@ pub(crate) use self::registration::Registration;
|
||||
mod stack;
|
||||
use self::stack::Stack;
|
||||
|
||||
use crate::executor::park::{Park, Unpark};
|
||||
use crate::runtime::{Park, Unpark};
|
||||
use crate::timer::atomic::AtomicU64;
|
||||
use crate::timer::clock::Clock;
|
||||
use crate::timer::wheel;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mod pad;
|
||||
mod rand;
|
||||
|
||||
pub(crate) use self::pad::CachePadded;
|
||||
|
||||
mod rand;
|
||||
pub(crate) use self::rand::FastRand;
|
||||
@@ -20,7 +20,11 @@ fn clock_and_timer_concurrent() {
|
||||
let when = Instant::now() + Duration::from_millis(5_000);
|
||||
let clock = Clock::new_with_now(MockNow(when));
|
||||
|
||||
let mut rt = runtime::Builder::new().clock(clock).build().unwrap();
|
||||
let mut rt = runtime::Builder::new()
|
||||
.thread_pool()
|
||||
.clock(clock)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ use std::task::{Context, Poll};
|
||||
#[test]
|
||||
fn single_thread() {
|
||||
// No panic when starting a runtime w/ a single thread
|
||||
let _ = runtime::Builder::new().num_threads(1).build();
|
||||
let _ = runtime::Builder::new().thread_pool().num_threads(1).build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -185,6 +185,7 @@ fn drop_threadpool_drops_futures() {
|
||||
let b = num_dec.clone();
|
||||
|
||||
let rt = runtime::Builder::new()
|
||||
.thread_pool()
|
||||
.after_start(move || {
|
||||
a.fetch_add(1, Relaxed);
|
||||
})
|
||||
@@ -223,6 +224,7 @@ fn after_start_and_before_stop_is_called() {
|
||||
let after_inner = after_start.clone();
|
||||
let before_inner = before_stop.clone();
|
||||
let mut rt = tokio::runtime::Builder::new()
|
||||
.thread_pool()
|
||||
.after_start(move || {
|
||||
after_inner.clone().fetch_add(1, Ordering::Relaxed);
|
||||
})
|
||||
@@ -263,7 +265,7 @@ fn blocking() {
|
||||
for _ in 0..4 {
|
||||
let block = block.clone();
|
||||
rt.spawn(async move {
|
||||
tokio::executor::blocking::in_place(move || {
|
||||
tokio::runtime::blocking::in_place(move || {
|
||||
block.wait();
|
||||
block.wait();
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user