lace_sans_io/core/
operand_cache.rs1use std::sync::{Arc, Mutex, PoisonError};
5
6use crate::logic::InterlaceModule;
7use crate::records::RecordHash;
8
9#[derive(Clone)]
14pub struct OperandCache(Arc<Mutex<Entries>>);
15
16struct Entries {
17 capacity: usize,
18 modules: Vec<(RecordHash, InterlaceModule)>,
19}
20
21impl OperandCache {
22 pub const DEFAULT_ENTRIES: usize = 32;
24
25 pub fn new(capacity: usize) -> Self {
27 Self(Arc::new(Mutex::new(Entries {
28 capacity,
29 modules: Vec::new(),
30 })))
31 }
32
33 pub fn set_capacity(&self, capacity: usize) {
35 let mut entries = self.lock();
36 entries.capacity = capacity;
37 entries.modules.truncate(capacity);
38 }
39
40 pub(crate) fn get(&self, hash: &RecordHash) -> Option<InterlaceModule> {
42 let mut entries = self.lock();
43 let index = entries.modules.iter().position(|(id, _)| id == hash)?;
44 let entry = entries.modules.remove(index);
45 let module = entry.1.clone();
46 entries.modules.insert(0, entry);
47 Some(module)
48 }
49
50 pub(crate) fn insert(&self, hash: RecordHash, module: InterlaceModule) {
52 let mut entries = self.lock();
53 if entries.capacity == 0 {
54 return;
55 }
56 entries.modules.retain(|(id, _)| *id != hash);
57 entries.modules.insert(0, (hash, module));
58 let capacity = entries.capacity;
59 entries.modules.truncate(capacity);
60 }
61
62 fn lock(&self) -> std::sync::MutexGuard<'_, Entries> {
63 self.0.lock().unwrap_or_else(PoisonError::into_inner)
65 }
66}
67
68impl Default for OperandCache {
69 fn default() -> Self {
70 Self::new(Self::DEFAULT_ENTRIES)
71 }
72}
73
74impl std::fmt::Debug for OperandCache {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 let entries = self.lock();
77 f.debug_struct("OperandCache")
78 .field("capacity", &entries.capacity)
79 .field("entries", &entries.modules.len())
80 .finish()
81 }
82}