#[diagnostic::on_unimplemented(
message = "`{Self}` is not a valid lock level",
note = "lock levels must implement the `IsLevel` trait; use `Level<N>`, `Base`, or manually implement `IsLevel`"
)]
pub trait IsLevel {}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be acquired after `{Before}`",
note = "locks must be acquired in ascending level order; once a higher-levelled lock is held, lower-levelled locks cannot be acquired for this key"
)]
pub trait LockAfter<Before: IsLevel>: IsLevel {}
#[diagnostic::on_unimplemented(
message = "`{Self}` has no next level (maximum depth reached)",
note = "the default maximum lock depth is 16 levels; enable the `levels-32` or `levels-64` feature for more, or flatten your hierarchy using `LockSet` for same-depth siblings"
)]
pub trait NextLevel: IsLevel {
type Next: IsLevel;
}
pub trait MinLevel<Other: IsLevel>: IsLevel {
type Min: IsLevel;
}
pub trait MaxLevel<Other: IsLevel>: IsLevel {
type Max: IsLevel;
}
pub trait MutexLevel {
type Lvl: IsLevel;
}
pub trait MaxLevelOf {
type Max: IsLevel;
}
impl<A: MutexLevel> MaxLevelOf for A {
type Max = A::Lvl;
}
impl<A: MutexLevel, B: MutexLevel> MaxLevelOf for (A, B)
where
A::Lvl: MaxLevel<B::Lvl>,
{
type Max = <A::Lvl as MaxLevel<B::Lvl>>::Max;
}
pub trait NewHigher<ChildT, R: crate::raw_mutex::RawMutex> {
type NextLvl: IsLevel;
fn new_higher(&self, data: ChildT) -> crate::mutex::Mutex<ChildT, Self::NextLvl, R>;
}
#[derive(Debug, Clone, Copy)]
pub struct Bottom;
impl IsLevel for Bottom {}
pub struct Level<const N: usize>;
impl<const N: usize> core::fmt::Debug for Level<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Level<{N}>")
}
}
#[allow(clippy::expl_impl_clone_on_copy)]
impl<const N: usize> Clone for Level<N> {
fn clone(&self) -> Self {
*self
}
}
impl<const N: usize> Copy for Level<N> {}
pub type Base = Level<0>;
macro_rules! generate_level_impls {
($max:expr, [$($n:expr),*]) => {
$(
impl IsLevel for Level<$n> {}
impl LockAfter<Bottom> for Level<$n> {}
)*
generate_lock_after_pairs!([$($n),*]);
generate_next_level!($max, [$($n),*]);
generate_min_max_pairs!([$($n),*]);
};
}
macro_rules! generate_lock_after_pairs {
([$first:expr $(, $rest:expr)*]) => {
$(
impl LockAfter<Level<$first>> for Level<$rest> {}
)*
generate_lock_after_pairs!([$($rest),*]);
};
([]) => {};
([$single:expr]) => {};
}
macro_rules! generate_next_level {
($max:expr, [$first:expr, $second:expr $(, $rest:expr)*]) => {
impl NextLevel for Level<$first> {
type Next = Level<$second>;
}
generate_next_level!($max, [$second $(, $rest)*]);
};
($max:expr, [$last:expr]) => {};
($max:expr, []) => {};
}
macro_rules! generate_min_max_pairs {
([$($n:expr),*]) => {
$(
impl MinLevel<Level<$n>> for Level<$n> {
type Min = Level<$n>;
}
impl MaxLevel<Level<$n>> for Level<$n> {
type Max = Level<$n>;
}
)*
generate_min_max_cross!([$($n),*]);
};
}
macro_rules! generate_min_max_cross {
([$first:expr $(, $rest:expr)*]) => {
$(
impl MinLevel<Level<$rest>> for Level<$first> {
type Min = Level<$first>;
}
impl MinLevel<Level<$first>> for Level<$rest> {
type Min = Level<$first>;
}
impl MaxLevel<Level<$rest>> for Level<$first> {
type Max = Level<$rest>;
}
impl MaxLevel<Level<$first>> for Level<$rest> {
type Max = Level<$rest>;
}
)*
generate_min_max_cross!([$($rest),*]);
};
([]) => {};
([$single:expr]) => {};
}
#[cfg(not(any(feature = "levels-32", feature = "levels-64")))]
generate_level_impls!(16, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
#[cfg(all(feature = "levels-32", not(feature = "levels-64")))]
generate_level_impls!(
32,
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31
]
);
#[cfg(feature = "levels-64")]
generate_level_impls!(
64,
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
]
);