add try_lock to MutexMap; allow TryFrom constructions

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2025-01-22 06:40:07 +00:00
parent 49023aa295
commit 7c0c029a4a
4 changed files with 71 additions and 19 deletions

View file

@ -725,7 +725,7 @@ pub(super) async fn force_set_room_state_from_server(
.save_state(room_id.clone().as_ref(), new_room_state)
.await?;
let state_lock = self.services.rooms.state.mutex.lock(&room_id).await;
let state_lock = self.services.rooms.state.mutex.lock(&*room_id).await;
self.services
.rooms
.state

View file

@ -1,7 +1,13 @@
use std::{fmt::Debug, hash::Hash, sync::Arc};
use std::{
fmt::Debug,
hash::Hash,
sync::{Arc, TryLockError::WouldBlock},
};
use tokio::sync::OwnedMutexGuard as Omg;
use crate::{err, Result};
/// Map of Mutexes
pub struct MutexMap<Key, Val> {
map: Map<Key, Val>,
@ -30,16 +36,17 @@ where
}
#[tracing::instrument(level = "trace", skip(self))]
pub async fn lock<K>(&self, k: &K) -> Guard<Key, Val>
pub async fn lock<'a, K>(&'a self, k: &'a K) -> Guard<Key, Val>
where
K: Debug + Send + ?Sized + Sync,
Key: for<'a> From<&'a K>,
Key: TryFrom<&'a K>,
<Key as TryFrom<&'a K>>::Error: Debug,
{
let val = self
.map
.lock()
.expect("locked")
.entry(k.into())
.entry(k.try_into().expect("failed to construct key"))
.or_default()
.clone();
@ -49,6 +56,51 @@ where
}
}
#[tracing::instrument(level = "trace", skip(self))]
pub fn try_lock<'a, K>(&self, k: &'a K) -> Result<Guard<Key, Val>>
where
K: Debug + Send + ?Sized + Sync,
Key: TryFrom<&'a K>,
<Key as TryFrom<&'a K>>::Error: Debug,
{
let val = self
.map
.lock()
.expect("locked")
.entry(k.try_into().expect("failed to construct key"))
.or_default()
.clone();
Ok(Guard::<Key, Val> {
map: Arc::clone(&self.map),
val: val.try_lock_owned().map_err(|_| err!("would yield"))?,
})
}
#[tracing::instrument(level = "trace", skip(self))]
pub fn try_try_lock<'a, K>(&self, k: &'a K) -> Result<Guard<Key, Val>>
where
K: Debug + Send + ?Sized + Sync,
Key: TryFrom<&'a K>,
<Key as TryFrom<&'a K>>::Error: Debug,
{
let val = self
.map
.try_lock()
.map_err(|e| match e {
| WouldBlock => err!("would block"),
| _ => panic!("{e:?}"),
})?
.entry(k.try_into().expect("failed to construct key"))
.or_default()
.clone();
Ok(Guard::<Key, Val> {
map: Arc::clone(&self.map),
val: val.try_lock_owned().map_err(|_| err!("would yield"))?,
})
}
#[must_use]
pub fn contains(&self, k: &Key) -> bool { self.map.lock().expect("locked").contains_key(k) }