Skip to content

Instantly share code, notes, and snippets.

@nmrshll
Created September 12, 2022 10:40
Show Gist options
  • Save nmrshll/b0a052ef1f90e036f76ddf85f8704e34 to your computer and use it in GitHub Desktop.
Save nmrshll/b0a052ef1f90e036f76ddf85f8704e34 to your computer and use it in GitHub Desktop.
Rust field cache
use std::future::Future;
use tokio::sync::RwLock;
pub struct Cache<T: Clone> {
item: RwLock<Option<T>>,
}
impl<T: Clone> Cache<T> {
pub fn new() -> Self {
Cache {
item: RwLock::new(None),
}
}
pub async fn get(&self) -> Option<T> {
let guard = self.item.read().await;
let inner = guard.clone();
inner
}
async fn set(&self, val: T) -> T {
let mut w_guard = self.item.write().await;
*w_guard = Some(val.clone());
val
}
pub async fn get_or_set(&self, val: T) -> T {
if let Some(inner) = self.item.read().await.clone() {
return inner;
} // read ref is dropped here
self.set(val).await
}
pub async fn get_or_init(&self, init: impl Future<Output = T>) -> T {
if let Some(inner) = self.item.read().await.clone() {
return inner;
} // read ref is dropped here
let new_val = init.await;
self.set(new_val).await
}
}
mod tests {
use super::Cache;
#[tokio::test]
async fn test_cache() {
let cache: Cache<String> = Cache::new();
let out = cache.get_or_set("hello".to_string()).await;
assert_eq!(out, "hello".to_string());
let out2 = cache.get_or_set("world".to_string()).await;
assert_eq!(out2, "hello".to_string());
let out3 = cache.get().await;
assert_eq!(out3, Some("hello".to_string()));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment