pub mod tuples;
use alloc::vec::Vec;
use crate::{
id::LockId,
level::IsLevel,
mutex::{Mutex, guard::MutexGuard},
raw_mutex::RawMutex,
};
pub trait MutexRef<'a> {
type Data: 'a;
type Lvl: IsLevel;
type RawMtx: RawMutex + 'a;
fn id(&self) -> LockId;
fn lock_ref(&'a self) -> MutexGuard<'a, Self::RawMtx, Self::Data>;
}
impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> MutexRef<'a> for &'a Mutex<T, Lvl, R> {
type Data = T;
type Lvl = Lvl;
type RawMtx = R;
fn id(&self) -> LockId {
Mutex::id(self)
}
fn lock_ref(&'a self) -> MutexGuard<'a, R, T> {
MutexGuard {
data: &self.data,
_raw_guard: self.raw.lock(),
}
}
}
#[cfg(target_has_atomic = "ptr")]
impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> MutexRef<'a>
for &'a alloc::sync::Arc<Mutex<T, Lvl, R>>
{
type Data = T;
type Lvl = Lvl;
type RawMtx = R;
fn id(&self) -> LockId {
Mutex::id(self)
}
fn lock_ref(&'a self) -> MutexGuard<'a, R, T> {
MutexGuard {
data: &self.data,
_raw_guard: self.raw.lock(),
}
}
}
impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> MutexRef<'a>
for &'a alloc::rc::Rc<Mutex<T, Lvl, R>>
{
type Data = T;
type Lvl = Lvl;
type RawMtx = R;
fn id(&self) -> LockId {
Mutex::id(self)
}
fn lock_ref(&'a self) -> MutexGuard<'a, R, T> {
MutexGuard {
data: &self.data,
_raw_guard: self.raw.lock(),
}
}
}
impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> MutexRef<'a>
for &'a alloc::boxed::Box<Mutex<T, Lvl, R>>
{
type Data = T;
type Lvl = Lvl;
type RawMtx = R;
fn id(&self) -> LockId {
Mutex::id(self)
}
fn lock_ref(&'a self) -> MutexGuard<'a, R, T> {
MutexGuard {
data: &self.data,
_raw_guard: self.raw.lock(),
}
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used as a lock group",
note = "use `&Mutex<T>` or tuples of mutex references to implement `Acquirable`"
)]
pub trait Acquirable<'a> {
type MinLvl: IsLevel;
type MaxLvl: IsLevel;
type Guard;
fn collect_ids(&self, out: &mut Vec<LockId>);
fn lock_sorted(&'a self, sorted_indices: &[usize]) -> Self::Guard;
}
impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> Acquirable<'a> for Mutex<T, Lvl, R> {
type MinLvl = Lvl;
type MaxLvl = Lvl;
type Guard = MutexGuard<'a, R, T>;
fn collect_ids(&self, out: &mut Vec<LockId>) {
out.push(self.id());
}
fn lock_sorted(&'a self, _sorted_indices: &[usize]) -> Self::Guard {
let raw_guard = self.raw.lock();
MutexGuard {
data: &self.data,
_raw_guard: raw_guard,
}
}
}
impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> Acquirable<'a> for &'a Mutex<T, Lvl, R> {
type MinLvl = Lvl;
type MaxLvl = Lvl;
type Guard = MutexGuard<'a, R, T>;
fn collect_ids(&self, out: &mut Vec<LockId>) {
out.push(self.id());
}
fn lock_sorted(&'a self, _sorted_indices: &[usize]) -> Self::Guard {
let raw_guard = self.raw.lock();
MutexGuard {
data: &self.data,
_raw_guard: raw_guard,
}
}
}
#[cfg(target_has_atomic = "ptr")]
impl<'a, T: Acquirable<'a>> Acquirable<'a> for alloc::sync::Arc<T> {
type MinLvl = T::MinLvl;
type MaxLvl = T::MaxLvl;
type Guard = T::Guard;
fn collect_ids(&self, out: &mut Vec<LockId>) {
T::collect_ids(self, out);
}
fn lock_sorted(&'a self, sorted_indices: &[usize]) -> Self::Guard {
T::lock_sorted(self, sorted_indices)
}
}
impl<'a, T: Acquirable<'a>> Acquirable<'a> for alloc::rc::Rc<T> {
type MinLvl = T::MinLvl;
type MaxLvl = T::MaxLvl;
type Guard = T::Guard;
fn collect_ids(&self, out: &mut Vec<LockId>) {
T::collect_ids(self, out);
}
fn lock_sorted(&'a self, sorted_indices: &[usize]) -> Self::Guard {
T::lock_sorted(self, sorted_indices)
}
}
impl<'a, T: Acquirable<'a>> Acquirable<'a> for alloc::boxed::Box<T> {
type MinLvl = T::MinLvl;
type MaxLvl = T::MaxLvl;
type Guard = T::Guard;
fn collect_ids(&self, out: &mut Vec<LockId>) {
T::collect_ids(self, out);
}
fn lock_sorted(&'a self, sorted_indices: &[usize]) -> Self::Guard {
T::lock_sorted(self, sorted_indices)
}
}
#[allow(clippy::indexing_slicing)] impl<'a, T: 'a, Lvl: IsLevel, R: RawMutex + 'a> Acquirable<'a> for &'a [Mutex<T, Lvl, R>] {
type MinLvl = Lvl;
type MaxLvl = Lvl;
type Guard = Vec<MutexGuard<'a, R, T>>;
fn collect_ids(&self, out: &mut Vec<LockId>) {
for m in *self {
out.push(m.id());
}
}
fn lock_sorted(&'a self, sorted_indices: &[usize]) -> Self::Guard {
sorted_indices
.iter()
.map(|&i| {
let raw_guard = self[i].raw.lock();
MutexGuard {
data: &self[i].data,
_raw_guard: raw_guard,
}
})
.collect()
}
}