#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#![deny(rust_2018_idioms, unsafe_op_in_unsafe_fn)]
#![warn(missing_docs)]
#![doc = include_str!("../README.md")]
pub mod algorithm;
mod core;
mod read;
mod util;
mod view;
mod write;
pub use read::*;
pub(crate) use util::loom;
pub use util::{deterministic::*, Alias};
pub use view::View;
pub use write::*;
use self::core::Core;
use std::{
collections::hash_map::RandomState,
fmt::{self, Debug, Formatter},
hash::{BuildHasher, Hash},
};
pub(crate) type Map<K, V, S = RandomState> = hashbrown::HashMap<Alias<K>, Alias<V>, S>;
pub fn new<K, V>() -> (WriteHandle<K, V>, ReadHandle<K, V>)
where
K: TrustedHashEq,
{
Builder::new().build()
}
pub fn with_capacity<K, V>(capacity: usize) -> (WriteHandle<K, V>, ReadHandle<K, V>)
where
K: TrustedHashEq,
{
Builder::new().with_capacity(capacity).build()
}
pub unsafe fn with_hasher<K, V, S>(hasher: S) -> (WriteHandle<K, V, S>, ReadHandle<K, V, S>)
where
K: TrustedHashEq,
S: Clone + BuildHasher,
{
unsafe { Builder::new().with_hasher(hasher).build() }
}
#[derive(Clone, Copy)]
pub struct Builder<S = RandomState> {
capacity: usize,
hasher: HasherGen<S>,
}
impl<S> Debug for Builder<S> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Builder")
.field("capacity", &self.capacity)
.field("hasher", &std::any::type_name::<S>())
.finish()
}
}
impl Builder<RandomState> {
pub fn new() -> Self {
Self {
capacity: 0,
hasher: HasherGen::MakeBoth(|| {
let hasher = RandomState::default();
(hasher.clone(), hasher)
}),
}
}
}
impl Default for Builder<RandomState> {
fn default() -> Self {
Self::new()
}
}
impl<S> Builder<S> {
pub fn with_capacity(self, capacity: usize) -> Self {
Self {
capacity,
hasher: self.hasher,
}
}
pub unsafe fn with_hasher<H>(self, hasher: H) -> Builder<H>
where
H: Clone + BuildHasher,
{
Builder {
capacity: self.capacity,
hasher: HasherGen::Clone(hasher, H::clone),
}
}
pub unsafe fn with_hasher_generator<H>(self, gen: fn() -> H) -> Builder<H>
where
H: BuildHasher,
{
Builder {
capacity: self.capacity,
hasher: HasherGen::Generate(gen),
}
}
pub fn build<K, V>(self) -> (WriteHandle<K, V, S>, ReadHandle<K, V, S>)
where
K: TrustedHashEq,
S: BuildHasher,
{
unsafe { self.build_assert_trusted() }
}
pub unsafe fn build_assert_trusted<K, V>(self) -> (WriteHandle<K, V, S>, ReadHandle<K, V, S>)
where
K: Hash + Eq,
S: BuildHasher,
{
unsafe { Core::build_map(self.into_args()) }
}
pub(crate) fn into_args(self) -> BuilderArgs<S> {
let (h1, h2) = self.hasher.generate();
BuilderArgs {
capacity: self.capacity,
h1,
h2,
}
}
}
#[derive(Clone, Copy)]
enum HasherGen<S> {
Generate(fn() -> S),
MakeBoth(fn() -> (S, S)),
Clone(S, fn(&S) -> S),
}
impl<S> HasherGen<S> {
fn generate(self) -> (S, S) {
match self {
Self::Generate(gen) => (gen(), gen()),
Self::MakeBoth(make_both) => make_both(),
Self::Clone(hasher, clone) => (clone(&hasher), hasher),
}
}
}
pub(crate) struct BuilderArgs<S> {
pub capacity: usize,
pub h1: S,
pub h2: S,
}
#[allow(dead_code)]
struct NotSendTypes;
#[allow(dead_code)]
struct NotSyncTypes;
#[cfg(test)]
mod tests {
use super::*;
use std::{collections::hash_map::DefaultHasher, marker::PhantomData};
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
#[derive(PartialEq, Eq, Hash)]
struct SendOnly(PhantomData<*const u8>);
unsafe impl Send for SendOnly {}
#[derive(PartialEq, Eq, Hash)]
struct SyncOnly(PhantomData<*const u8>);
unsafe impl Sync for SyncOnly {}
#[derive(PartialEq, Eq, Hash)]
struct SendSync;
impl BuildHasher for SendSync {
type Hasher = DefaultHasher;
fn build_hasher(&self) -> Self::Hasher {
unimplemented!()
}
}
#[test]
fn send_types() {
assert_send::<ReadHandle<SendSync, SendSync, SendSync>>();
assert_send::<WriteHandle<SendSync, SendSync, SendSync>>();
assert_send::<View<ReadGuard<'_, SendSync, SendSync, SendSync>>>();
assert_send::<Leaked<SendOnly>>();
}
#[test]
fn sync_types() {
assert_sync::<ReadHandle<SendSync, SendSync, SendSync>>();
assert_sync::<View<ReadGuard<'_, SendSync, SendSync, SendSync>>>();
assert_sync::<Leaked<SyncOnly>>();
}
}