use std::sync::Arc;
use tokio::sync::{Mutex, RwLock, Semaphore};
#[derive(Debug)]
pub struct ThreadingProvider {
cpu_pool: Arc<Semaphore>,
io_pool: Arc<Semaphore>,
}
impl Default for ThreadingProvider {
fn default() -> Self {
Self::new()
}
}
impl ThreadingProvider {
pub fn new() -> Self {
let cpu_count = num_cpus::get();
Self {
cpu_pool: Arc::new(Semaphore::new(cpu_count)),
io_pool: Arc::new(Semaphore::new(cpu_count * 2)),
}
}
pub async fn execute_cpu_task<F, T>(&self, task: F) -> crate::Result<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
let _permit = self
.cpu_pool
.acquire()
.await
.map_err(|e| crate::Error::storage(e.to_string()))?;
let result = tokio::task::spawn_blocking(task)
.await
.map_err(|e| crate::Error::storage(e.to_string()))?;
Ok(result)
}
pub async fn execute_io_task<F, T>(&self, task: F) -> crate::Result<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
{
let _permit = self
.io_pool
.acquire()
.await
.map_err(|e| crate::Error::storage(e.to_string()))?;
let result = tokio::task::spawn_blocking(task)
.await
.map_err(|e| crate::Error::storage(e.to_string()))?;
Ok(result)
}
pub fn create_mutex<T>(&self, value: T) -> Arc<Mutex<T>> {
Arc::new(Mutex::new(value))
}
pub fn create_rwlock<T>(&self, value: T) -> Arc<RwLock<T>> {
Arc::new(RwLock::new(value))
}
pub fn cpu_count(&self) -> usize {
num_cpus::get()
}
}