froodi 1.0.0-beta.15

An ergonomic Rust IoC container
Documentation
#![allow(dead_code)]

use ahash::AHasher;
use core::{
    array,
    hash::{Hash, Hasher as _},
};
use parking_lot::Mutex;

use crate::utils::thread_safety::RcThreadSafety;

#[allow(clippy::cast_possible_truncation)]
fn stripe_index<const N: usize>(val: impl Hash) -> usize {
    let mut hasher = AHasher::default();
    val.hash(&mut hasher);

    hasher.finish() as usize % N
}

#[derive(Clone)]
pub(crate) struct StripedLocks<const N: usize> {
    stripes: RcThreadSafety<[Mutex<()>; N]>,
}

impl<const N: usize> StripedLocks<N> {
    #[inline]
    #[must_use]
    fn new() -> Self {
        Self {
            stripes: RcThreadSafety::new(array::from_fn(|_| Mutex::new(()))),
        }
    }
}

impl<const N: usize> StripedLocks<N> {
    #[inline]
    #[must_use]
    pub(crate) fn get(&self, val: impl Hash) -> &Mutex<()> {
        &self.stripes[stripe_index::<N>(val)]
    }
}

impl<const N: usize> Default for StripedLocks<N> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(feature = "async")]
mod async_impl {
    use tokio::sync::Mutex;

    use super::{array, stripe_index, Hash, RcThreadSafety};

    #[derive(Clone)]
    pub(crate) struct StripedSharedLocks<const N: usize> {
        stripes: RcThreadSafety<[Mutex<()>; N]>,
    }

    impl<const N: usize> StripedSharedLocks<N> {
        #[inline]
        #[must_use]
        fn new() -> Self {
            Self {
                stripes: RcThreadSafety::new(array::from_fn(|_| Mutex::new(()))),
            }
        }
    }

    impl<const N: usize> StripedSharedLocks<N> {
        #[inline]
        #[must_use]
        pub(crate) fn get(&self, val: impl Hash) -> &Mutex<()> {
            &self.stripes[stripe_index::<N>(val)]
        }
    }

    impl<const N: usize> Default for StripedSharedLocks<N> {
        #[inline]
        fn default() -> Self {
            Self::new()
        }
    }
}

#[cfg(feature = "async")]
pub(crate) use async_impl::StripedSharedLocks;