use std::num::NonZeroUsize;
use crate::runtime::bootstrap::pools::BlockingPools;
use crate::runtime::error::Error;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BlockingPoolPolicy {
mode: Mode,
max_workers: Option<usize>,
}
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
enum Mode {
PerWorker,
Shared,
}
impl BlockingPoolPolicy {
#[must_use]
pub const fn per_worker() -> Self {
Self {
mode: Mode::PerWorker,
max_workers: None,
}
}
#[must_use]
pub const fn shared() -> Self {
Self {
mode: Mode::Shared,
max_workers: None,
}
}
#[must_use]
pub const fn max(mut self, max_workers: usize) -> Self {
self.max_workers = Some(max_workers);
self
}
pub(crate) const fn mode_label(&self) -> &'static str {
match self.mode {
Mode::PerWorker => "per_worker",
Mode::Shared => "shared",
}
}
pub(crate) fn into_pools(self) -> Result<BlockingPools, Error> {
match self.mode {
Mode::PerWorker => {
let max_workers = validated_max(self.max_workers)?;
Ok(BlockingPools::per_worker(max_workers))
}
Mode::Shared => {
let max_workers = validated_max(self.max_workers)?;
Ok(BlockingPools::shared(max_workers))
}
}
}
}
impl Default for BlockingPoolPolicy {
fn default() -> Self {
Self::shared()
}
}
fn validated_max(max_workers: Option<usize>) -> Result<Option<NonZeroUsize>, Error> {
max_workers
.map(|max_workers| NonZeroUsize::new(max_workers).ok_or_else(Error::invalid_blocking_pool_limit))
.transpose()
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))] mod tests {
use super::*;
#[test]
fn per_worker_into_pools_is_per_worker() {
assert!(
matches!(
BlockingPoolPolicy::per_worker().into_pools().unwrap(),
BlockingPools::PerWorker(None)
),
"expected PerWorker variant"
);
}
#[test]
fn shared_into_pools_is_shared() {
assert!(
matches!(BlockingPoolPolicy::shared().into_pools().unwrap(), BlockingPools::Shared(_)),
"expected Shared variant"
);
}
#[test]
fn maximum_applies_to_both_pool_modes() {
assert!(matches!(
BlockingPoolPolicy::per_worker().max(3).into_pools().unwrap(),
BlockingPools::PerWorker(Some(max)) if max.get() == 3
));
assert!(matches!(
BlockingPoolPolicy::shared().max(4).into_pools().unwrap(),
BlockingPools::Shared(pool) if pool.max_thread_count() == 4
));
}
}