#[cfg(any(feature = "parking_lot", feature = "tokio"))]
use crate::locks::LockValue;
#[cfg(any(feature = "parking_lot", feature = "tokio"))]
use crate::lock_query::LockQuery;
#[cfg(any(feature = "parking_lot", feature = "tokio"))]
use crate::lock_lazy::LockLazyQuery;
#[cfg(any(feature = "parking_lot", feature = "tokio"))]
use crate::lock_join::LockJoinQuery;
#[cfg(any(feature = "parking_lot", feature = "tokio"))]
use std::collections::HashMap;
#[cfg(any(feature = "parking_lot", feature = "tokio"))]
use std::sync::Arc;
#[cfg(feature = "parking_lot")]
#[derive(Clone, Debug)]
pub struct ParkingLotRwLockWrapper<T>(Arc<parking_lot::RwLock<T>>);
#[cfg(feature = "parking_lot")]
impl<T> ParkingLotRwLockWrapper<T> {
pub fn new(value: T) -> Self {
Self(Arc::new(parking_lot::RwLock::new(value)))
}
pub fn inner(&self) -> &Arc<parking_lot::RwLock<T>> {
&self.0
}
}
#[cfg(feature = "parking_lot")]
impl<T> LockValue<T> for ParkingLotRwLockWrapper<T> {
fn with_value<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T) -> R,
{
let guard = self.0.read();
Some(f(&*guard))
}
}
#[cfg(feature = "parking_lot")]
#[derive(Clone, Debug)]
pub struct ParkingLotMutexWrapper<T>(Arc<parking_lot::Mutex<T>>);
#[cfg(feature = "parking_lot")]
impl<T> ParkingLotMutexWrapper<T> {
pub fn new(value: T) -> Self {
Self(Arc::new(parking_lot::Mutex::new(value)))
}
pub fn inner(&self) -> &Arc<parking_lot::Mutex<T>> {
&self.0
}
}
#[cfg(feature = "parking_lot")]
impl<T> LockValue<T> for ParkingLotMutexWrapper<T> {
fn with_value<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T) -> R,
{
let guard = self.0.lock();
Some(f(&*guard))
}
}
#[cfg(feature = "parking_lot")]
pub trait ParkingLotQueryExt<V> {
fn lock_query(&self) -> LockQuery<'_, V, ParkingLotRwLockWrapper<V>>;
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotRwLockWrapper<V>, impl Iterator<Item = &ParkingLotRwLockWrapper<V>>>;
}
#[cfg(feature = "parking_lot")]
impl<K, V: 'static> ParkingLotQueryExt<V> for HashMap<K, ParkingLotRwLockWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_query(&self) -> LockQuery<'_, V, ParkingLotRwLockWrapper<V>> {
let locks: Vec<_> = self.values().collect();
LockQuery::from_locks(locks)
}
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotRwLockWrapper<V>, impl Iterator<Item = &ParkingLotRwLockWrapper<V>>> {
LockLazyQuery::new(self.values())
}
}
#[cfg(feature = "parking_lot")]
pub trait ParkingLotMutexQueryExt<V> {
fn lock_query(&self) -> LockQuery<'_, V, ParkingLotMutexWrapper<V>>;
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotMutexWrapper<V>, impl Iterator<Item = &ParkingLotMutexWrapper<V>>>;
}
#[cfg(feature = "parking_lot")]
impl<K, V: 'static> ParkingLotMutexQueryExt<V> for HashMap<K, ParkingLotMutexWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_query(&self) -> LockQuery<'_, V, ParkingLotMutexWrapper<V>> {
let locks: Vec<_> = self.values().collect();
LockQuery::from_locks(locks)
}
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotMutexWrapper<V>, impl Iterator<Item = &ParkingLotMutexWrapper<V>>> {
LockLazyQuery::new(self.values())
}
}
#[cfg(feature = "parking_lot")]
pub trait ParkingLotJoinExt<V> {
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotRwLockWrapper<R>>)
-> LockJoinQuery<'a, V, R, ParkingLotRwLockWrapper<V>, ParkingLotRwLockWrapper<R>>
where
R: 'static;
}
#[cfg(feature = "parking_lot")]
impl<K, V: 'static> ParkingLotJoinExt<V> for HashMap<K, ParkingLotRwLockWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotRwLockWrapper<R>>)
-> LockJoinQuery<'a, V, R, ParkingLotRwLockWrapper<V>, ParkingLotRwLockWrapper<R>>
where
R: 'static,
{
let left_locks: Vec<_> = self.values().collect();
let right_locks: Vec<_> = right.values().collect();
LockJoinQuery::new(left_locks, right_locks)
}
}
#[cfg(feature = "parking_lot")]
pub trait ParkingLotMutexJoinExt<V> {
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotMutexWrapper<R>>)
-> LockJoinQuery<'a, V, R, ParkingLotMutexWrapper<V>, ParkingLotMutexWrapper<R>>
where
R: 'static;
}
#[cfg(feature = "parking_lot")]
impl<K, V: 'static> ParkingLotMutexJoinExt<V> for HashMap<K, ParkingLotMutexWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, ParkingLotMutexWrapper<R>>)
-> LockJoinQuery<'a, V, R, ParkingLotMutexWrapper<V>, ParkingLotMutexWrapper<R>>
where
R: 'static,
{
let left_locks: Vec<_> = self.values().collect();
let right_locks: Vec<_> = right.values().collect();
LockJoinQuery::new(left_locks, right_locks)
}
}
#[cfg(feature = "tokio")]
#[derive(Clone, Debug)]
pub struct TokioRwLockWrapper<T>(Arc<tokio::sync::RwLock<T>>);
#[cfg(feature = "tokio")]
impl<T> TokioRwLockWrapper<T> {
pub fn new(value: T) -> Self {
Self(Arc::new(tokio::sync::RwLock::new(value)))
}
pub fn inner(&self) -> &Arc<tokio::sync::RwLock<T>> {
&self.0
}
}
#[cfg(feature = "tokio")]
impl<T> LockValue<T> for TokioRwLockWrapper<T> {
fn with_value<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T) -> R,
{
let guard = self.0.blocking_read();
Some(f(&*guard))
}
}
#[cfg(feature = "tokio")]
#[derive(Clone, Debug)]
pub struct TokioMutexWrapper<T>(Arc<tokio::sync::Mutex<T>>);
#[cfg(feature = "tokio")]
impl<T> TokioMutexWrapper<T> {
pub fn new(value: T) -> Self {
Self(Arc::new(tokio::sync::Mutex::new(value)))
}
pub fn inner(&self) -> &Arc<tokio::sync::Mutex<T>> {
&self.0
}
}
#[cfg(feature = "tokio")]
impl<T> LockValue<T> for TokioMutexWrapper<T> {
fn with_value<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T) -> R,
{
let guard = self.0.blocking_lock();
Some(f(&*guard))
}
}
#[cfg(feature = "tokio")]
pub trait TokioLockQueryExt<V> {
fn lock_query(&self) -> LockQuery<'_, V, TokioRwLockWrapper<V>>;
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioRwLockWrapper<V>, impl Iterator<Item = &TokioRwLockWrapper<V>>>;
}
#[cfg(feature = "tokio")]
impl<K, V: 'static> TokioLockQueryExt<V> for HashMap<K, TokioRwLockWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_query(&self) -> LockQuery<'_, V, TokioRwLockWrapper<V>> {
let locks: Vec<_> = self.values().collect();
LockQuery::from_locks(locks)
}
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioRwLockWrapper<V>, impl Iterator<Item = &TokioRwLockWrapper<V>>> {
LockLazyQuery::new(self.values())
}
}
#[cfg(feature = "tokio")]
pub trait TokioMutexQueryExt<V> {
fn lock_query(&self) -> LockQuery<'_, V, TokioMutexWrapper<V>>;
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioMutexWrapper<V>, impl Iterator<Item = &TokioMutexWrapper<V>>>;
}
#[cfg(feature = "tokio")]
impl<K, V: 'static> TokioMutexQueryExt<V> for HashMap<K, TokioMutexWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_query(&self) -> LockQuery<'_, V, TokioMutexWrapper<V>> {
let locks: Vec<_> = self.values().collect();
LockQuery::from_locks(locks)
}
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, TokioMutexWrapper<V>, impl Iterator<Item = &TokioMutexWrapper<V>>> {
LockLazyQuery::new(self.values())
}
}
#[cfg(feature = "tokio")]
pub trait TokioLockJoinExt<V> {
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioRwLockWrapper<R>>)
-> LockJoinQuery<'a, V, R, TokioRwLockWrapper<V>, TokioRwLockWrapper<R>>
where
R: 'static;
}
#[cfg(feature = "tokio")]
impl<K, V: 'static> TokioLockJoinExt<V> for HashMap<K, TokioRwLockWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioRwLockWrapper<R>>)
-> LockJoinQuery<'a, V, R, TokioRwLockWrapper<V>, TokioRwLockWrapper<R>>
where
R: 'static,
{
let left_locks: Vec<_> = self.values().collect();
let right_locks: Vec<_> = right.values().collect();
LockJoinQuery::new(left_locks, right_locks)
}
}
#[cfg(feature = "tokio")]
pub trait TokioMutexJoinExt<V> {
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioMutexWrapper<R>>)
-> LockJoinQuery<'a, V, R, TokioMutexWrapper<V>, TokioMutexWrapper<R>>
where
R: 'static;
}
#[cfg(feature = "tokio")]
impl<K, V: 'static> TokioMutexJoinExt<V> for HashMap<K, TokioMutexWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_join<'a, R>(&'a self, right: &'a HashMap<impl std::hash::Hash + Eq, TokioMutexWrapper<R>>)
-> LockJoinQuery<'a, V, R, TokioMutexWrapper<V>, TokioMutexWrapper<R>>
where
R: 'static,
{
let left_locks: Vec<_> = self.values().collect();
let right_locks: Vec<_> = right.values().collect();
LockJoinQuery::new(left_locks, right_locks)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_wrapper() {
let wrapper = ParkingLotRwLockWrapper::new(42);
let result = wrapper.with_value(|v| *v * 2);
assert_eq!(result, Some(84));
}
#[cfg(feature = "tokio")]
#[test]
fn test_tokio_wrapper() {
let wrapper = TokioRwLockWrapper::new(42);
let result = wrapper.with_value(|v| *v * 2);
assert_eq!(result, Some(84));
}
}