use crate::ArenaProvider;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
pub struct Pool<'p> {
pool: PoolRef<'p>,
pub(crate) spmd: Mutex<()>,
workspace: ArenaProvider,
entries: AtomicU64,
broadcasts: AtomicU64,
inline_runs: AtomicU64,
}
enum PoolRef<'p> {
Borrowed(&'p rayon::ThreadPool),
Owned(Box<rayon::ThreadPool>),
Shared(Arc<rayon::ThreadPool>),
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct PoolStats {
pub entries: u64,
pub broadcasts: u64,
pub inline_runs: u64,
}
impl<'p> Pool<'p> {
pub fn borrow(pool: &'p rayon::ThreadPool) -> Self {
Self::with(PoolRef::Borrowed(pool))
}
fn with(pool: PoolRef<'p>) -> Self {
Self {
pool,
spmd: Mutex::new(()),
workspace: ArenaProvider::new(),
entries: AtomicU64::new(0),
broadcasts: AtomicU64::new(0),
inline_runs: AtomicU64::new(0),
}
}
pub fn workspace(&self) -> &ArenaProvider {
&self.workspace
}
pub fn trim_workspace(&self) {
use crate::WorkspaceProvider;
self.workspace.trim();
}
pub fn size(&self) -> usize {
self.tp().current_num_threads()
}
pub fn rayon_pool(&self) -> &rayon::ThreadPool {
self.tp()
}
pub(crate) fn tp(&self) -> &rayon::ThreadPool {
match &self.pool {
PoolRef::Borrowed(p) => p,
PoolRef::Owned(p) => p,
PoolRef::Shared(p) => p,
}
}
pub fn into_owned(self) -> Option<rayon::ThreadPool> {
match self.pool {
PoolRef::Owned(p) => Some(*p),
PoolRef::Borrowed(_) | PoolRef::Shared(_) => None,
}
}
pub fn stats(&self) -> PoolStats {
PoolStats {
entries: self.entries.load(Ordering::Relaxed),
broadcasts: self.broadcasts.load(Ordering::Relaxed),
inline_runs: self.inline_runs.load(Ordering::Relaxed),
}
}
pub fn reset_stats(&self) {
self.entries.store(0, Ordering::Relaxed);
self.broadcasts.store(0, Ordering::Relaxed);
self.inline_runs.store(0, Ordering::Relaxed);
}
pub(crate) fn is_worker(&self) -> bool {
self.tp().current_thread_index().is_some()
}
pub(crate) fn count_entry(&self) {
self.entries.fetch_add(1, Ordering::Relaxed);
}
pub(crate) fn count_broadcast(&self) {
self.broadcasts.fetch_add(1, Ordering::Relaxed);
}
pub(crate) fn count_inline(&self) {
self.inline_runs.fetch_add(1, Ordering::Relaxed);
}
}
impl Pool<'static> {
pub fn shared(pool: Arc<rayon::ThreadPool>) -> Self {
Self::with(PoolRef::Shared(pool))
}
pub fn owned(pool: rayon::ThreadPool) -> Self {
Self::with(PoolRef::Owned(Box::new(pool)))
}
}
impl std::fmt::Debug for Pool<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Pool")
.field("size", &self.size())
.field("stats", &self.stats())
.finish()
}
}