use crate::store::StoreItem;
use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
use std::cell::UnsafeCell;
use std::collections::hash_map::RandomState;
use std::collections::HashMap;
use std::convert::TryInto;
use std::fmt::{Debug, Display, Formatter};
use std::hash::BuildHasher;
use std::time::Duration;
pub struct ValueRef<'a, V, S = RandomState> {
_guard: RwLockReadGuard<'a, HashMap<u64, StoreItem<V>, S>>,
val: &'a StoreItem<V>,
}
unsafe impl<'a, V: Send, S: BuildHasher> Send for ValueRef<'a, V, S> {}
unsafe impl<'a, V: Send + Sync, S: BuildHasher> Sync for ValueRef<'a, V, S> {}
impl<'a, V, S: BuildHasher> ValueRef<'a, V, S> {
#[inline]
pub(crate) fn new(
guard: RwLockReadGuard<'a, HashMap<u64, StoreItem<V>, S>>,
val: &'a StoreItem<V>,
) -> Self {
Self { _guard: guard, val }
}
#[inline]
pub fn value(&self) -> &V {
self.val.value.get()
}
#[inline]
pub fn release(self) {
drop(self)
}
#[inline]
pub fn ttl(&self) -> Duration {
self.val.expiration.get_ttl()
}
}
impl<'a, V: Copy, S: BuildHasher> ValueRef<'a, V, S> {
#[inline]
pub fn read(self) -> V {
let v = *self.value();
drop(self);
v
}
}
impl<'a, V, S: BuildHasher> AsRef<V> for ValueRef<'a, V, S> {
fn as_ref(&self) -> &V {
self.value()
}
}
impl<'a, V: Debug, S: BuildHasher> Debug for ValueRef<'a, V, S> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.val)
}
}
impl<'a, V: Display, S: BuildHasher> Display for ValueRef<'a, V, S> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value())
}
}
pub struct ValueRefMut<'a, V, S = RandomState> {
_guard: RwLockWriteGuard<'a, HashMap<u64, StoreItem<V>, S>>,
val: &'a mut V,
}
unsafe impl<'a, V: Send, S: BuildHasher> Send for ValueRefMut<'a, V, S> {}
unsafe impl<'a, V: Send + Sync, S: BuildHasher> Sync for ValueRefMut<'a, V, S> {}
impl<'a, V, S: BuildHasher> ValueRefMut<'a, V, S> {
#[inline]
pub(crate) fn new(
guard: RwLockWriteGuard<'a, HashMap<u64, StoreItem<V>, S>>,
val: &'a mut V,
) -> Self {
Self { _guard: guard, val }
}
#[inline]
pub fn value(&self) -> &V {
self.val
}
#[inline]
pub fn value_mut(&mut self) -> &mut V {
self.val
}
#[inline]
pub fn write(&mut self, val: V) {
*self.val = val
}
#[inline]
pub fn write_once(self, val: V) {
*self.val = val;
self.release();
}
#[inline]
pub fn release(self) {
drop(self)
}
}
impl<'a, V: Clone, S: BuildHasher> ValueRefMut<'a, V, S> {
pub fn clone_inner(&self) -> V {
self.val.clone()
}
}
impl<'a, V: Copy, S: BuildHasher> ValueRefMut<'a, V, S> {
pub fn read(self) -> V {
let v = *self.val;
drop(self);
v
}
}
impl<'a, V: Debug, S: BuildHasher> Debug for ValueRefMut<'a, V, S> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.val)
}
}
impl<'a, V: Display, S: BuildHasher> Display for ValueRefMut<'a, V, S> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.val)
}
}
impl<'a, V, S: BuildHasher> AsRef<V> for ValueRefMut<'a, V, S> {
fn as_ref(&self) -> &V {
self.value()
}
}
impl<'a, V, S: BuildHasher> AsMut<V> for ValueRefMut<'a, V, S> {
fn as_mut(&mut self) -> &mut V {
self.value_mut()
}
}
#[repr(transparent)]
pub struct SharedValue<T> {
value: UnsafeCell<T>,
}
impl<T: Clone> Clone for SharedValue<T> {
fn clone(&self) -> Self {
let inner = self.get().clone();
Self {
value: UnsafeCell::new(inner),
}
}
}
unsafe impl<T: Send> Send for SharedValue<T> {}
unsafe impl<T: Sync> Sync for SharedValue<T> {}
impl<T> SharedValue<T> {
pub const fn new(value: T) -> Self {
Self {
value: UnsafeCell::new(value),
}
}
pub fn get(&self) -> &T {
unsafe { &*self.value.get() }
}
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.value.get() }
}
pub fn into_inner(self) -> T {
self.value.into_inner()
}
pub(crate) fn as_ptr(&self) -> *mut T {
self.value.get()
}
}
pub(crate) fn vec_to_array<T, const N: usize>(v: Vec<T>) -> [T; N] {
v.try_into()
.unwrap_or_else(|v: Vec<T>| panic!("Expected a Vec of length {} but it was {}", N, v.len()))
}
pub(crate) unsafe fn change_lifetime_const<'a, 'b, T>(x: &'a T) -> &'b T {
&*(x as *const T)
}
#[cfg(test)]
mod test {
use crate::store::StoreItem;
use crate::ttl::Time;
use crate::utils::{
change_lifetime_const,
SharedValue,
};
use crate::{ValueRef, ValueRefMut};
use parking_lot::RwLock;
use std::collections::HashMap;
#[test]
fn test_value_ref() {
let mut m = HashMap::new();
m.insert(
1,
StoreItem {
key: 1,
conflict: 0,
value: SharedValue::new(3),
expiration: Time::now(),
},
);
m.insert(
2,
StoreItem {
key: 2,
conflict: 0,
value: SharedValue::new(3),
expiration: Time::now(),
},
);
let lm = RwLock::new(m);
let l = lm.read();
let item = l.get(&1).unwrap();
let v = unsafe { change_lifetime_const(item) };
let vr = ValueRef::new(l, v);
assert_eq!(vr.as_ref(), &3);
eprintln!("{}", vr);
eprintln!("{:?}", vr);
}
#[test]
fn test_value_ref_mut() {
let mut m = HashMap::new();
m.insert(
1,
StoreItem {
key: 1,
conflict: 0,
value: SharedValue::new(3),
expiration: Time::now(),
},
);
m.insert(
2,
StoreItem {
key: 2,
conflict: 0,
value: SharedValue::new(3),
expiration: Time::now(),
},
);
let lm = RwLock::new(m);
let l = lm.write();
let v = unsafe { &mut *l.get(&1).unwrap().value.as_ptr() };
let mut vr = ValueRefMut::new(l, v);
assert_eq!(vr.as_ref(), &3);
assert_eq!(vr.as_mut(), &mut 3);
assert_eq!(vr.value(), &3);
assert_eq!(vr.clone_inner(), 3);
eprintln!("{}", vr);
eprintln!("{:?}", vr);
vr.write_once(4);
}
#[test]
fn test_shared_value() {
let sv = SharedValue::new(3);
assert_eq!(sv.get(), &3);
}
}