writium_cache/
item.rs

1use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
2use std::sync::atomic::{AtomicBool, Ordering};
3use writium::prelude::*;
4
5const ERR_POISONED_THREAD: &str = "Current thread is poisoned.";
6
7/// Unit of storage in `Cache`.
8pub struct CacheItem<T: 'static> {
9    id: String,
10    data: RwLock<T>,
11    is_dirty: AtomicBool,
12}
13impl<T: 'static> CacheItem<T> {
14    pub fn new(id: &str, data: T) -> CacheItem<T> {
15        CacheItem {
16            id: id.to_owned(),
17            data: RwLock::new(data),
18            is_dirty: AtomicBool::new(false),
19        }
20    }
21
22    /// Get the ID of current 
23    pub fn id(&self) -> &str {
24        &self.id
25    }
26
27    /// Lock the internal mutex and return a read guard holding the cached data.
28    pub fn read<'guard, 'lock: 'guard>(&'lock self) -> Result<RwLockReadGuard<'guard, T>> {
29        self.data.read()
30            .map_err(|_| Error::internal(ERR_POISONED_THREAD))
31    }
32    /// Lock the internal mutex and return a write guard holding the cached
33    /// data.
34    pub fn write<'guard, 'lock: 'guard>(&'lock self) -> Result<RwLockWriteGuard<'guard, T>> {
35        self.set_dirty();
36        self.data.write()
37            .map_err(|_| Error::internal(ERR_POISONED_THREAD))
38    }
39
40    /// If the flag is set, it means that cached data has been modified or is
41    /// newly created. The change should be propagated to local storage.
42    pub fn is_dirty(&self) -> bool {
43        self.is_dirty.load(Ordering::Acquire)
44    }
45    /// Set the dirty flag on.
46    pub(crate) fn set_dirty(&self) {
47        self.is_dirty.store(true, Ordering::Release)
48    }
49}