/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use core::hash::Hash; use std::hash::Hasher; use ahash::AHasher; use tokio::sync::{Mutex, MutexGuard}; pub struct MutexMap { map: Box<[Mutex]>, mask: u64, hasher: AHasher, } pub struct MutexMapLockError; pub type Result = std::result::Result; #[allow(clippy::mutex_atomic)] impl MutexMap { pub fn with_capacity(size: usize) -> MutexMap { let size = size.next_power_of_two(); MutexMap { map: (0..size) .map(|_| T::default().into()) .collect::>>() .into_boxed_slice(), mask: (size - 1) as u64, hasher: AHasher::default(), } } pub async fn lock(&self, key: U) -> MutexGuard<'_, T> where U: Into + Copy, { let hash = key.into() & self.mask; self.map[hash as usize].lock().await } /*pub async fn try_lock(&self, key: U, timeout: Duration) -> Option> where U: Into + Copy, { let hash = key.into() & self.mask; self.map[hash as usize].try_lock(timeout).await }*/ pub async fn lock_hash(&self, key: U) -> MutexGuard<'_, T> where U: Hash, { let mut hasher = self.hasher.clone(); key.hash(&mut hasher); let hash = hasher.finish() & self.mask; self.map[hash as usize].lock().await } /*pub async fn try_lock_hash(&self, key: U, timeout: Duration) -> Option> where U: Hash, { let mut hasher = self.hasher.clone(); key.hash(&mut hasher); let hash = hasher.finish() & self.mask; self.map[hash as usize].try_lock_for(timeout).await }*/ }