mod current;
mod idle;
use self::idle::Idle;
mod owned;
use self::owned::Owned;
mod queue;
mod spawner;
pub(crate) use self::spawner::Spawner;
mod slice;
mod shared;
use self::shared::Shared;
mod worker;
use worker::Worker;
cfg_blocking! {
pub(crate) use worker::block_in_place;
}
#[cfg(test)]
mod tests;
#[cfg(not(loom))]
const LOCAL_QUEUE_CAPACITY: usize = 256;
#[cfg(loom)]
const LOCAL_QUEUE_CAPACITY: usize = 2;
use crate::runtime::{self, Parker};
use crate::task::JoinHandle;
use std::fmt;
use std::future::Future;
pub(crate) struct ThreadPool {
spawner: Spawner,
}
pub(crate) struct Workers {
workers: Vec<Worker>,
}
impl ThreadPool {
pub(crate) fn new(pool_size: usize, parker: Parker) -> (ThreadPool, Workers) {
let (pool, workers) = worker::create_set(pool_size, parker);
let spawner = Spawner::new(pool);
let pool = ThreadPool { spawner };
(pool, Workers { workers })
}
pub(crate) fn spawner(&self) -> &Spawner {
&self.spawner
}
pub(crate) fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
self.spawner.spawn(future)
}
pub(crate) fn block_on<F>(&self, future: F) -> F::Output
where
F: Future,
{
let mut enter = crate::runtime::enter();
enter.block_on(future).expect("failed to park thread")
}
}
impl fmt::Debug for ThreadPool {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("ThreadPool").finish()
}
}
impl Drop for ThreadPool {
fn drop(&mut self) {
self.spawner.workers().close();
}
}
impl Workers {
pub(crate) fn spawn(self, rt: &runtime::Handle) {
rt.enter(|| {
for worker in self.workers {
runtime::spawn_blocking(move || worker.run());
}
});
}
}