use std::{sync::Arc, thread::JoinHandle, time::Duration};
use crossbeam::channel::{bounded, Receiver};
use crate::vec::{RefGuard, SyncVec};
pub struct CachePackage<T: Default> {
list: Arc<SyncVec<T>>,
receiver_index: Receiver<usize>,
_thread_join: JoinHandle<()>,
}
impl<T: Default + 'static> CachePackage<T> {
pub fn new(cap: usize, mem_size: usize) -> Self {
let list = Arc::new(SyncVec::new());
let list_c = list.clone();
let (tx, rx) = bounded(cap);
if mem_size < 1024 {
debug!("cache_package mem_size: {} bt", mem_size);
} else if mem_size < 1024 * 1024 {
debug!("cache_package mem_size: {:.2} kb", mem_size as f64 / 1024.0);
} else {
debug!(
"cache_package mem_size: {:.2} mb",
mem_size as f64 / 1024.0 / 1024.0
);
}
let _thread_join = std::thread::Builder::new()
.stack_size(mem_size)
.spawn(move || loop {
let i = list_c.push_return(T::default());
if let Err(_e) = tx.send(i) {
error!("cache_package tx.send error[{i}]: {_e}");
#[cfg(debug_assertions)]
println!("cache_package tx.send error[{i}]: {_e}");
std::thread::sleep(std::time::Duration::from_secs(1));
}
})
.unwrap();
Self { list, receiver_index: rx, _thread_join }
}
#[inline(always)]
pub fn next(&self) -> RefGuard<'_, T> {
let i = self.receiver_index.recv().unwrap_or_else(|_e| {
let i = self.list.push_return(T::default());
warn!("cache_package.try_recv error[{i}]: {_e}");
i
});
self.list.get_uncheck(i)
}
}