use std::collections::HashMap;
use std::sync::{Arc, Mutex};
pub(crate) struct SobolDvCache {
inner: Mutex<HashMap<u32, (u64, usize)>>,
}
impl SobolDvCache {
pub(crate) fn new() -> Arc<Self> {
Arc::new(Self {
inner: Mutex::new(HashMap::new()),
})
}
pub fn get(&self, dimension: u32) -> Option<(u64, usize)> {
let map = self.inner.lock().unwrap_or_else(|p| p.into_inner());
map.get(&dimension).copied()
}
pub unsafe fn insert(&self, dimension: u32, ptr: u64, num_u32s: usize) {
let mut map = self.inner.lock().unwrap_or_else(|p| p.into_inner());
map.entry(dimension).or_insert((ptr, num_u32s));
}
}
impl Drop for SobolDvCache {
fn drop(&mut self) {
let mut map = self.inner.lock().unwrap_or_else(|p| p.into_inner());
for (ptr, _size) in map.drain().map(|(_, v)| v) {
if ptr != 0 {
unsafe {
let r = cudarc::driver::sys::cuMemFree_v2(ptr);
#[cfg(debug_assertions)]
if r != cudarc::driver::sys::CUresult::CUDA_SUCCESS
&& r != cudarc::driver::sys::CUresult::CUDA_ERROR_INVALID_CONTEXT
&& r != cudarc::driver::sys::CUresult::CUDA_ERROR_DEINITIALIZED
{
eprintln!(
"[numr::cuda] SobolDvCache::drop: cuMemFree_v2 failed for \
0x{ptr:x}: {r:?} (device buffer leaked)"
);
}
#[cfg(not(debug_assertions))]
let _ = r;
}
}
}
}
}