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
7pub 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 pub fn id(&self) -> &str {
24 &self.id
25 }
26
27 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 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 pub fn is_dirty(&self) -> bool {
43 self.is_dirty.load(Ordering::Acquire)
44 }
45 pub(crate) fn set_dirty(&self) {
47 self.is_dirty.store(true, Ordering::Release)
48 }
49}