79 lines
1.9 KiB
Rust
79 lines
1.9 KiB
Rust
use alloc::{string::String, vec::Vec, collections::BTreeMap};
|
|
use libcortex_a9::mutex::Mutex;
|
|
use cslice::{CSlice, AsCSlice};
|
|
use core::mem::transmute;
|
|
use core::str;
|
|
|
|
use crate::artiq_raise;
|
|
|
|
|
|
#[derive(Debug)]
|
|
struct Entry {
|
|
data: Vec<i32>,
|
|
borrowed: bool
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct Cache {
|
|
entries: BTreeMap<String, Entry>
|
|
}
|
|
|
|
impl Cache {
|
|
pub const fn new() -> Cache {
|
|
Cache { entries: BTreeMap::new() }
|
|
}
|
|
|
|
pub fn get(&mut self, key: &str) -> *const [i32] {
|
|
match self.entries.get_mut(key) {
|
|
None => &[],
|
|
Some(ref mut entry) => {
|
|
entry.borrowed = true;
|
|
&entry.data[..]
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn put(&mut self, key: &str, data: &[i32]) -> Result<(), ()> {
|
|
match self.entries.get_mut(key) {
|
|
None => (),
|
|
Some(ref mut entry) => {
|
|
if entry.borrowed { return Err(()) }
|
|
entry.data = Vec::from(data);
|
|
return Ok(())
|
|
}
|
|
}
|
|
|
|
self.entries.insert(String::from(key), Entry {
|
|
data: Vec::from(data),
|
|
borrowed: false
|
|
});
|
|
Ok(())
|
|
}
|
|
|
|
pub unsafe fn unborrow(&mut self) {
|
|
for (_key, entry) in self.entries.iter_mut() {
|
|
entry.borrowed = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
static CACHE: Mutex<Cache> = Mutex::new(Cache::new());
|
|
|
|
pub extern fn get(key: CSlice<u8>) -> CSlice<'static, i32> {
|
|
let value = CACHE.lock().get(str::from_utf8(key.as_ref()).unwrap());
|
|
unsafe {
|
|
transmute::<*const [i32], &'static [i32]>(value).as_c_slice()
|
|
}
|
|
}
|
|
|
|
pub extern fn put(key: CSlice<u8>, list: CSlice<i32>) {
|
|
let result = CACHE.lock().put(str::from_utf8(key.as_ref()).unwrap(), list.as_ref());
|
|
if result.is_err() {
|
|
artiq_raise!("CacheError", "cannot put into a busy cache row");
|
|
}
|
|
}
|
|
|
|
pub unsafe fn unborrow() {
|
|
CACHE.lock().unborrow();
|
|
}
|