ff7cd562af
- implement more readers - fix downloading of bioformats jar - (mostly) compatible with python version
94 lines
2.7 KiB
Rust
94 lines
2.7 KiB
Rust
use std::hash::{Hash, Hasher};
|
|
use std::path::{Path, PathBuf};
|
|
use std::sync::{LazyLock, RwLock};
|
|
use indexmap::{Equivalent, IndexMap};
|
|
use ndarray::IxDyn;
|
|
use crate::error::Error;
|
|
use crate::readers::ArrayT;
|
|
|
|
static CACHE: LazyLock<RwLock<IndexMap<ViewHash, ArrayT<IxDyn>>>> =
|
|
LazyLock::new(|| RwLock::new(IndexMap::new()));
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
struct ViewHash {
|
|
reader: String,
|
|
path: PathBuf,
|
|
series: usize,
|
|
position: usize,
|
|
c: isize,
|
|
z: isize,
|
|
t: isize,
|
|
}
|
|
|
|
impl Hash for ViewHash {
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
self.reader.as_str().hash(state);
|
|
self.path.as_path().hash(state);
|
|
self.series.hash(state);
|
|
self.position.hash(state);
|
|
self.c.hash(state);
|
|
self.z.hash(state);
|
|
self.t.hash(state);
|
|
}
|
|
}
|
|
|
|
impl ViewHash {
|
|
fn new(reader: String, path: PathBuf, series: usize, position: usize, c: isize, z: isize, t: isize) -> Self {
|
|
Self { reader, path, series, position, c, z, t }
|
|
}
|
|
}
|
|
|
|
struct ViewEquiv<'a> {
|
|
reader: &'a str,
|
|
path: &'a Path,
|
|
series: usize,
|
|
position: usize,
|
|
c: isize,
|
|
z: isize,
|
|
t: isize,
|
|
}
|
|
|
|
impl Hash for ViewEquiv<'_> {
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
self.reader.hash(state);
|
|
self.path.hash(state);
|
|
self.series.hash(state);
|
|
self.position.hash(state);
|
|
self.c.hash(state);
|
|
self.z.hash(state);
|
|
self.t.hash(state);
|
|
}
|
|
}
|
|
|
|
impl<'a> ViewEquiv<'a> {
|
|
fn new(reader: &'a str, path: &'a Path, series: usize, position: usize, c: isize, z: isize, t: isize) -> ViewEquiv<'a> {
|
|
Self { reader, path, series, position, c, z, t }
|
|
}
|
|
}
|
|
|
|
impl Equivalent<ViewEquiv<'_>> for ViewHash {
|
|
fn equivalent(&self, key: &ViewEquiv) -> bool {
|
|
(self.reader == key.reader) && (self.path == key.path) && (self.series == key.series) && (self.position == key.position) && (self.c == key.c) && (self.z == key.z) && (self.t == key.t)
|
|
}
|
|
}
|
|
|
|
impl Equivalent<ViewHash> for ViewEquiv<'_> {
|
|
fn equivalent(&self, key: &ViewHash) -> bool {
|
|
key.equivalent(self)
|
|
}
|
|
}
|
|
|
|
pub fn cache_get_or_insert(f: &dyn Fn() -> ArrayT<IxDyn>, reader: &str, path: &Path, series: usize, position: usize, c: isize, z: isize, t: isize) -> Result<ArrayT<IxDyn>, Error> {
|
|
if let Some(frame) = CACHE.read().unwrap().get(&ViewEquiv::new(reader, path, series, position, c, z, t)) {
|
|
Ok(frame.clone())
|
|
} else {
|
|
let a = f();
|
|
let mut cache = CACHE.write().unwrap();
|
|
cache.insert(ViewHash::new(reader.to_string(), path.to_path_buf(), series, position, c, z, t), a.clone());
|
|
// TODO: find an IndexMapDeque to pop efficiently at the other end
|
|
while cache.len() > 1024 {
|
|
cache.pop();
|
|
}
|
|
Ok(a)
|
|
}
|
|
} |