#![deny(missing_docs)]
use std::sync::{atomic, Arc, Mutex};
mod inner;
pub(crate) type Epochs = Arc<Mutex<Vec<Arc<atomic::AtomicUsize>>>>;
use fxhash::FxBuildHasher;
use inner::Inner;
use std::fmt;
use std::hash::{BuildHasher, Hash};
pub struct Updater<V>(pub(crate) Box<dyn Fn(&mut V) + Send + Sync>);
impl<V> Updater<V> {
#[inline]
pub fn eval(&self, value: &mut V) {
(*self.0)(value)
}
}
impl<V> PartialEq for Updater<V> {
#[inline]
fn eq(&self, other: &Self) -> bool {
&*self.0 as *const _ == &*other.0 as *const _
}
}
impl<V> Eq for Updater<V> {}
impl<V> fmt::Debug for Updater<V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("Updater")
.field(&format_args!("{:p}", &*self.0 as *const _))
.finish()
}
}
#[derive(PartialEq, Eq, Debug)]
#[non_exhaustive]
pub enum MonoOperation<K, V> {
Insert(K, V),
Update(K, Updater<V>),
Remove(K),
Purge,
}
mod write;
pub use write::MonoWriteHandle;
mod read;
pub use read::{MonoReadHandle, MonoReadHandleFactory};
pub struct MonoOptions<M, S>
where
S: BuildHasher,
{
meta: M,
hasher: S,
capacity: Option<usize>,
}
impl Default for MonoOptions<(), FxBuildHasher> {
fn default() -> Self {
MonoOptions {
meta: (),
hasher: FxBuildHasher::default(),
capacity: None,
}
}
}
impl<M, S> MonoOptions<M, S>
where
S: BuildHasher,
{
pub fn with_meta<M2>(self, meta: M2) -> MonoOptions<M2, S> {
MonoOptions {
meta,
hasher: self.hasher,
capacity: self.capacity,
}
}
pub fn with_hasher<S2>(self, hash_builder: S2) -> MonoOptions<M, S2>
where
S2: BuildHasher,
{
MonoOptions {
meta: self.meta,
hasher: hash_builder,
capacity: self.capacity,
}
}
pub fn with_capacity(self, capacity: usize) -> MonoOptions<M, S> {
MonoOptions {
meta: self.meta,
hasher: self.hasher,
capacity: Some(capacity),
}
}
#[allow(clippy::type_complexity)]
pub fn construct<K, V>(self) -> (MonoReadHandle<K, V, M, S>, MonoWriteHandle<K, V, M, S>)
where
K: Eq + Hash + Clone,
S: BuildHasher + Clone,
V: Clone,
M: 'static + Clone,
{
let epochs = Default::default();
let inner = if let Some(cap) = self.capacity {
Inner::with_capacity_and_hasher(self.meta, cap, self.hasher)
} else {
Inner::with_hasher(self.meta, self.hasher)
};
let mut w_handle = inner.clone();
w_handle.mark_ready();
let r = read::new(inner, Arc::clone(&epochs));
let w = write::new(w_handle, epochs, r.clone());
(r, w)
}
}
#[allow(clippy::type_complexity)]
pub fn new<K, V>() -> (
MonoReadHandle<K, V, (), FxBuildHasher>,
MonoWriteHandle<K, V, (), FxBuildHasher>,
)
where
K: Eq + Hash + Clone,
V: Clone,
{
MonoOptions::default().construct()
}
#[allow(clippy::type_complexity)]
pub fn with_meta<K, V, M>(
meta: M,
) -> (
MonoReadHandle<K, V, M, FxBuildHasher>,
MonoWriteHandle<K, V, M, FxBuildHasher>,
)
where
K: Eq + Hash + Clone,
V: Clone,
M: 'static + Clone,
{
MonoOptions::default().with_meta(meta).construct()
}
#[allow(clippy::type_complexity)]
pub fn with_hasher<K, V, M, S>(
meta: M,
hasher: S,
) -> (MonoReadHandle<K, V, M, S>, MonoWriteHandle<K, V, M, S>)
where
K: Eq + Hash + Clone,
V: Clone,
M: 'static + Clone,
S: BuildHasher + Clone,
{
MonoOptions::default()
.with_hasher(hasher)
.with_meta(meta)
.construct()
}