use crate::inner::Inner;
use crate::values::Values;
use std::borrow::Borrow;
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash};
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::sync::atomic;
use std::sync::atomic::AtomicPtr;
use std::sync::{self, Arc};
use std::{cell, fmt, mem};
mod guard;
pub use guard::ReadGuard;
mod factory;
pub use factory::ReadHandleFactory;
mod read_ref;
pub use read_ref::{MapReadRef, ReadGuardIter};
pub struct ReadHandle<K, V, M = (), S = RandomState>
where
K: Eq + Hash,
S: BuildHasher,
{
pub(crate) inner: sync::Arc<AtomicPtr<Inner<K, ManuallyDrop<V>, M, S>>>,
pub(crate) epochs: crate::Epochs,
epoch: sync::Arc<sync::atomic::AtomicUsize>,
epoch_i: usize,
my_epoch: sync::atomic::AtomicUsize,
_not_sync_no_feature: PhantomData<cell::Cell<()>>,
}
impl<K, V, M, S> Drop for ReadHandle<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
fn drop(&mut self) {
let e = self.epochs.lock().unwrap().remove(self.epoch_i);
assert!(Arc::ptr_eq(&e, &self.epoch));
}
}
impl<K, V, M, S> fmt::Debug for ReadHandle<K, V, M, S>
where
K: Eq + Hash + fmt::Debug,
S: BuildHasher,
M: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ReadHandle")
.field("epochs", &self.epochs)
.field("epoch", &self.epoch)
.field("my_epoch", &self.my_epoch)
.finish()
}
}
impl<K, V, M, S> Clone for ReadHandle<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
fn clone(&self) -> Self {
ReadHandle::new(
sync::Arc::clone(&self.inner),
sync::Arc::clone(&self.epochs),
)
}
}
pub(crate) fn new<K, V, M, S>(
inner: Inner<K, ManuallyDrop<V>, M, S>,
epochs: crate::Epochs,
) -> ReadHandle<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
let store = Box::into_raw(Box::new(inner));
ReadHandle::new(sync::Arc::new(AtomicPtr::new(store)), epochs)
}
impl<K, V, M, S> ReadHandle<K, V, M, S>
where
K: Eq + Hash,
S: BuildHasher,
{
fn new(
inner: sync::Arc<AtomicPtr<Inner<K, ManuallyDrop<V>, M, S>>>,
epochs: crate::Epochs,
) -> Self {
let epoch = sync::Arc::new(atomic::AtomicUsize::new(0));
let epoch_i = epochs.lock().unwrap().insert(Arc::clone(&epoch));
Self {
epochs,
epoch,
epoch_i,
my_epoch: atomic::AtomicUsize::new(0),
inner,
_not_sync_no_feature: PhantomData,
}
}
pub fn factory(&self) -> ReadHandleFactory<K, V, M, S> {
ReadHandleFactory {
inner: sync::Arc::clone(&self.inner),
epochs: sync::Arc::clone(&self.epochs),
}
}
}
impl<K, V, M, S> ReadHandle<K, V, M, S>
where
K: Eq + Hash,
V: Eq + Hash,
S: BuildHasher,
M: Clone,
{
fn handle(&self) -> Option<ReadGuard<'_, Inner<K, ManuallyDrop<V>, M, S>>> {
let epoch = self.my_epoch.fetch_add(1, atomic::Ordering::Relaxed);
self.epoch.store(epoch + 1, atomic::Ordering::Release);
atomic::fence(atomic::Ordering::SeqCst);
let r_handle = self.inner.load(atomic::Ordering::Acquire);
let r_handle = unsafe { r_handle.as_ref() };
if let Some(r_handle) = r_handle {
Some(ReadGuard {
handle: &self.epoch,
epoch,
t: r_handle,
})
} else {
self.epoch.store(
(epoch + 1) | 1usize << (mem::size_of::<usize>() * 8 - 1),
atomic::Ordering::Release,
);
None
}
}
pub(crate) unsafe fn hasher(&self) -> &S {
self.inner
.load(atomic::Ordering::Acquire)
.as_ref()
.unwrap()
.data
.hasher()
}
pub fn read(&self) -> Option<MapReadRef<'_, K, V, M, S>> {
let guard = self.handle()?;
if !guard.is_ready() {
return None;
}
Some(MapReadRef { guard })
}
pub fn len(&self) -> usize {
self.read().map_or(0, |x| x.len())
}
pub fn is_empty(&self) -> bool {
self.read().map_or(true, |x| x.is_empty())
}
pub fn meta(&self) -> Option<ReadGuard<'_, M>> {
Some(self.handle()?.map_ref(|inner| &inner.meta))
}
fn get_raw<Q: ?Sized>(&self, key: &Q) -> Option<ReadGuard<'_, Values<ManuallyDrop<V>, S>>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let inner = self.handle()?;
if !inner.is_ready() {
return None;
}
inner.map_opt(|inner| inner.data.get(key))
}
#[inline]
pub fn get<'rh, Q: ?Sized>(&'rh self, key: &'_ Q) -> Option<ReadGuard<'rh, Values<V, S>>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
Some(self.get_raw(key.borrow())?.map_ref(Values::user_friendly))
}
#[inline]
pub fn get_one<'rh, Q: ?Sized>(&'rh self, key: &'_ Q) -> Option<ReadGuard<'rh, V>>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.get_raw(key.borrow())?
.map_opt(|x| x.user_friendly().get_one())
}
pub fn meta_get<Q: ?Sized>(&self, key: &Q) -> Option<(Option<ReadGuard<'_, Values<V, S>>>, M)>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let inner = self.handle()?;
if !inner.is_ready() {
return None;
}
let meta = inner.meta.clone();
let res = inner
.map_opt(|inner| inner.data.get(key))
.map(|r| r.map_ref(Values::user_friendly));
Some((res, meta))
}
pub fn is_destroyed(&self) -> bool {
self.handle().is_none()
}
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.read().map_or(false, |x| x.contains_key(key))
}
pub fn contains_value<Q: ?Sized, W: ?Sized>(&self, key: &Q, value: &W) -> bool
where
K: Borrow<Q>,
V: Borrow<W>,
Q: Hash + Eq,
W: Hash + Eq,
{
self.get_raw(key.borrow())
.map(|x| x.user_friendly().contains(value))
.unwrap_or(false)
}
pub fn map_into<Map, Collector, Target>(&self, mut f: Map) -> Collector
where
Map: FnMut(&K, &Values<V, S>) -> Target,
Collector: FromIterator<Target>,
{
Collector::from_iter(self.read().iter().flatten().map(|(k, v)| f(k, v)))
}
}
#[cfg(test)]
mod test {
use crate::new;
#[test]
fn reserve_and_fit() {
const MIN: usize = (1 << 4) + 1;
const MAX: usize = 1 << 6;
let (r, mut w) = new();
w.reserve(0, MAX).refresh();
assert!(r.get_raw(&0).unwrap().capacity() >= MAX);
for i in 0..MIN {
w.insert(0, i);
}
w.fit_all().refresh();
assert!(r.get_raw(&0).unwrap().capacity() < MAX);
}
}