diff options
| author | Mica White <botahamec@outlook.com> | 2026-08-26 20:46:31 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2026-08-26 20:46:31 -0400 |
| commit | 55b3a2425b242fbc5c6e471f220eeb8b949e8751 (patch) | |
| tree | 5ceb7910b60cc7331024b7ce1d49ec259e0302a8 /src/context/tuple.rs | |
| parent | 6f6e030ea7edb9d155ebf21b5d42936c20801b50 (diff) | |
Add tests
Diffstat (limited to 'src/context/tuple.rs')
| -rw-r--r-- | src/context/tuple.rs | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/src/context/tuple.rs b/src/context/tuple.rs new file mode 100644 index 0000000..9bca72e --- /dev/null +++ b/src/context/tuple.rs @@ -0,0 +1,847 @@ +use std::marker::PhantomData; + +use crate::{ + context::{ContextGuard, LockingIterator, LockingTuple}, + lockable::{Lockable, RawLock, Sharable}, + ThreadKey, +}; + +impl<'c, A, B, O> LockingTuple<'c, A, B, O> { + fn transmute<C>(self) -> LockingTuple<'c, C, B, O> { + LockingTuple { + _lockable: PhantomData, + key: self.key, + tuple: self.tuple, + outer: self.outer, + } + } +} + +macro_rules! lock_impl { + ($self: expr, $field: tt) => { + unsafe { + $self.tuple.$field.raw_write(); + ( + ContextGuard { + _key: &$self.key, + guard: $self.tuple.$field.guard(), + }, + $self.transmute(), + ) + } + }; +} + +macro_rules! try_lock_impl { + ($self: expr, $field: tt) => { + unsafe { + if $self.tuple.$field.raw_try_write() { + Ok(( + ContextGuard { + _key: $self.key, + guard: $self.tuple.$field.guard(), + }, + $self.transmute(), + )) + } else { + Err($self) + } + } + }; +} + +macro_rules! lock_mut_impl { + ($self: expr, $field: tt) => { + unsafe { + $self.tuple.$field.raw_write(); + ContextGuard { + _key: $self.key, + guard: $self.tuple.$field.guard(), + } + } + }; +} + +macro_rules! try_lock_mut_impl { + ($self: expr, $field: tt) => { + unsafe { + if $self.tuple.$field.raw_try_write() { + Some(ContextGuard { + _key: $self.key, + guard: $self.tuple.$field.guard(), + }) + } else { + None + } + } + }; +} + +macro_rules! read_impl { + ($self: expr, $field: tt) => { + unsafe { + $self.tuple.$field.raw_read(); + ( + ContextGuard { + _key: &$self.key, + guard: $self.tuple.$field.read_guard(), + }, + $self.transmute(), + ) + } + }; +} + +macro_rules! try_read_impl { + ($self: expr, $field: tt) => { + unsafe { + if $self.tuple.$field.raw_try_read() { + Ok(( + ContextGuard { + _key: $self.key, + guard: $self.tuple.$field.read_guard(), + }, + $self.transmute(), + )) + } else { + Err($self) + } + } + }; +} + +macro_rules! read_mut_impl { + ($self: expr, $field: tt) => { + unsafe { + $self.tuple.$field.raw_read(); + ContextGuard { + _key: $self.key, + guard: $self.tuple.$field.read_guard(), + } + } + }; +} + +macro_rules! try_read_mut_impl { + ($self: expr, $field: tt) => { + unsafe { + if $self.tuple.$field.raw_try_read() { + Some(ContextGuard { + _key: $self.key, + guard: $self.tuple.$field.read_guard(), + }) + } else { + None + } + } + }; +} + +macro_rules! recurse_impl { + ($self: expr, $field: tt) => { + LockingTuple { + _lockable: PhantomData, + key: $self.key, + tuple: &$self.tuple.$field, + outer: $self.transmute(), + } + }; +} + +macro_rules! recurse_iter_impl { + ($self: expr, $field: tt) => { + LockingIterator { + key: $self.key, + iterator: $self.tuple.$field.into_iter(), + outer: $self.transmute(), + } + }; +} + +type LockReturn<'a, 'context, Guarded, L, C, O> = ( + ContextGuard<'a, <Guarded as Lockable>::Guard<'a>, ThreadKey>, + LockingTuple<'context, L, C, O>, +); + +type TryLockReturn<'a, 'context, Guarded, L, C, O, This> = + Result<LockReturn<'a, 'context, Guarded, L, C, O>, This>; + +type ReadReturn<'a, 'context, Guarded, L, C, O> = ( + ContextGuard<'a, <Guarded as Sharable>::ReadGuard<'a>, ThreadKey>, + LockingTuple<'context, L, C, O>, +); + +type TryReadReturn<'a, 'context, Guarded, L, C, O, This> = + Result<ReadReturn<'a, 'context, Guarded, L, C, O>, This>; + +type RecurseReturn<'context, Inner, L, C, O> = + LockingTuple<'context, Inner, Inner, LockingTuple<'context, L, C, O>>; + +type RecurseIterReturn<'context, Inner, L, C, O> = LockingIterator< + 'context, + <&'context Inner as IntoIterator>::IntoIter, + LockingTuple<'context, L, C, O>, +>; + +impl<T, C, Outer> LockingTuple<'_, T, C, Outer> { + /// Exit out of the current scope of the locking tuple into the parent. + pub fn exit(self) -> Outer { + self.outer + } +} + +impl<'context, A: RawLock + Lockable, Outer> LockingTuple<'context, (A,), (A,), Outer> { + /// Lock the first element, and return a new tuple where the first element + /// is inaccessible. + #[must_use] + pub fn lock_0<'a>(self) -> LockReturn<'a, 'context, A, ((),), (A,), Outer> + where + 'context: 'a, + { + lock_impl!(self, 0) + } + + /// Attempts to lock the first element without blocking, and return a new tuple + /// where the first element is inaccessible. + /// + /// # Errors + /// + /// If the element is already locked, `Err` is returned with the original + /// tuple. + pub fn try_lock_0<'a>(self) -> TryLockReturn<'a, 'context, A, ((),), (A,), Outer, Self> + where + 'context: 'a, + { + try_lock_impl!(self, 0) + } + + /// Lock the first element. The tuple becomes unusable until the returned + /// guard is dropped. + #[must_use] + pub fn lock_mut_0(&mut self) -> ContextGuard<'_, A::Guard<'_>, ThreadKey> { + lock_mut_impl!(self, 0) + } + + /// Attempts to lock the first element without blocking. If successful, the + /// tuple becomes unusable until the returned guard is dropped. If the element + /// is already locked, `None` is returned. + #[must_use] + pub fn try_lock_mut_0(&mut self) -> Option<ContextGuard<'_, A::Guard<'_>, ThreadKey>> { + try_lock_mut_impl!(self, 0) + } +} + +impl<'context, A: RawLock + Sharable, Outer> LockingTuple<'context, (A,), (A,), Outer> { + /// Acquire a shared lock to the first element, and return a new tuple where + /// the first element is inaccessible. + #[must_use] + pub fn read_0<'a>(self) -> ReadReturn<'a, 'context, A, ((),), (A,), Outer> + where + 'context: 'a, + { + read_impl!(self, 0) + } + + /// Attempts to acquire a shared lock the first element without blocking, and + /// return a new tuple where the first element is inaccessible. + /// + /// # Errors + /// + /// If the element is already exclusively locked, `Err` is returned with the original + /// tuple. + pub fn try_read_0<'a>(self) -> TryReadReturn<'a, 'context, A, ((),), (A,), Outer, Self> + where + 'context: 'a, + { + try_read_impl!(self, 0) + } + + /// Acquire a shared lock to the first element. The tuple becomes unusable + /// until the returned guard is dropped. + #[must_use] + pub fn read_mut_0(&mut self) -> ContextGuard<'_, A::ReadGuard<'_>, ThreadKey> { + read_mut_impl!(self, 0) + } + + /// Attempts to acquire a shared lock the first element without blocking. If + /// successful, the tuple becomes unusable until the returned guard is + /// dropped. If the element is already exclusively locked, `None` is returned. + #[must_use] + pub fn try_read_mut_0(&mut self) -> Option<ContextGuard<'_, A::ReadGuard<'_>, ThreadKey>> { + try_read_mut_impl!(self, 0) + } +} + +impl<'context, A, O> LockingTuple<'context, (A,), (A,), O> { + /// Consume the tuple, and return the first element as a new tuple. + #[must_use] + pub fn recurse_0(self) -> RecurseReturn<'context, A, ((),), (A,), O> { + recurse_impl!(self, 0) + } + + /// Consume the tuple, and return the first element as a locking iterator. + pub fn recurse_0_iter(self) -> RecurseIterReturn<'context, A, ((),), (A,), O> + where + &'context A: IntoIterator, + { + recurse_iter_impl!(self, 0) + } +} + +impl<'context, A: RawLock + Lockable, B, B0, O> LockingTuple<'context, (A, B), (A, B0), O> { + /// Lock the first element, and return a new tuple where the first element + /// is inaccessible. + #[must_use] + pub fn lock_0<'a>(self) -> LockReturn<'a, 'context, A, ((), B), (A, B0), O> + where + 'context: 'a, + { + lock_impl!(self, 0) + } + + /// Lock the first element. The tuple becomes unusable until the returned + /// guard is dropped. + #[must_use] + pub fn lock_mut_0(&mut self) -> ContextGuard<'_, A::Guard<'_>, ThreadKey> { + lock_mut_impl!(self, 0) + } + + /// Attempts to lock the first element without blocking, and return a new tuple + /// where the first element is inaccessible. + /// + /// # Errors + /// + /// If the element is already locked, `Err` is returned with the original + /// tuple. + pub fn try_lock_0<'a>(self) -> TryLockReturn<'a, 'context, A, ((), B), (A, B0), O, Self> + where + 'context: 'a, + { + try_lock_impl!(self, 0) + } + + /// Attempts to lock the first element without blocking. If successful, the + /// tuple becomes unusable until the returned guard is dropped. If the element + /// is already locked, `None` is returned. + #[must_use] + pub fn try_lock_mut_0(&mut self) -> Option<ContextGuard<'_, A::Guard<'_>, ThreadKey>> { + try_lock_mut_impl!(self, 0) + } +} + +impl<'context, A: RawLock + Sharable, B, B0, O> LockingTuple<'context, (A, B), (A, B0), O> { + /// Acquire a shared lock to the first element, and return a new tuple where + /// the first element is inaccessible. + #[must_use] + pub fn read_0<'a>(self) -> ReadReturn<'a, 'context, A, ((), B), (A, B0), O> + where + 'context: 'a, + { + read_impl!(self, 0) + } + + /// Attempts to acquire a shared lock the first element without blocking, and + /// return a new tuple where the first element is inaccessible. + /// + /// # Errors + /// + /// If the element is already exclusively locked, `Err` is returned with the original + /// tuple. + pub fn try_read_0<'a>(self) -> TryReadReturn<'a, 'context, A, ((), B), (A, B0), O, Self> + where + 'context: 'a, + { + try_read_impl!(self, 0) + } + + /// Acquire a shared lock to the first element. The tuple becomes unusable + /// until the returned guard is dropped. + #[must_use] + pub fn read_mut_0(&mut self) -> ContextGuard<'_, A::ReadGuard<'_>, ThreadKey> { + read_mut_impl!(self, 0) + } + + /// Attempts to acquire a shared lock the first element without blocking. If + /// successful, the tuple becomes unusable until the returned guard is + /// dropped. If the element is already exclusively locked, `None` is returned. + #[must_use] + pub fn try_read_mut_0(&mut self) -> Option<ContextGuard<'_, A::ReadGuard<'_>, ThreadKey>> { + try_read_mut_impl!(self, 0) + } +} + +impl<'context, A, B, B0, O> LockingTuple<'context, (A, B), (A, B0), O> { + /// Consume the tuple, and return the first element as a new tuple. + #[must_use] + pub fn recurse_0(self) -> RecurseReturn<'context, A, ((), B), (A, B0), O> { + recurse_impl!(self, 0) + } + + /// Consume the tuple, and return the first element as a locking iterator. + pub fn recurse_0_iter(self) -> RecurseIterReturn<'context, A, ((), B), (A, B0), O> + where + &'context A: IntoIterator, + { + recurse_iter_impl!(self, 0) + } +} + +impl<'context, A: Lockable + RawLock, B, O> LockingTuple<'context, (A, B), (A, B), O> { + /// Lock the first element, and return the second element as a new tuple. + #[must_use] + pub fn lock_and_recurse<'a>( + self, + ) -> ( + ContextGuard<'a, <A as Lockable>::Guard<'a>, ThreadKey>, + LockingTuple<'context, B, B, O>, + ) + where + 'context: 'a, + { + unsafe { + self.tuple.0.raw_write(); + ( + ContextGuard { + _key: self.key, + guard: self.tuple.0.guard(), + }, + LockingTuple { + _lockable: PhantomData, + key: self.key, + tuple: &self.tuple.1, + outer: self.outer, + }, + ) + } + } +} + +impl<'context, A, A0, B: RawLock + Lockable, O> LockingTuple<'context, (A, B), (A0, B), O> { + /// Lock the second element, and return a new tuple where the first and second + /// elements are inaccessible. + #[must_use] + pub fn lock_1<'a>(self) -> LockReturn<'a, 'context, B, ((), ()), (A0, B), O> + where + 'context: 'a, + { + lock_impl!(self, 1) + } + + /// Lock the second element. The tuple becomes unusable until the returned + /// guard is dropped. + #[must_use] + pub fn lock_mut_1(&mut self) -> ContextGuard<'_, B::Guard<'_>, ThreadKey> { + lock_mut_impl!(self, 1) + } + + /// Attempts to lock the second element without blocking, and return a new tuple + /// where the first element is inaccessible. + /// + /// # Errors + /// + /// If the element is already locked, `Err` is returned with the original + /// tuple. + pub fn try_lock_1<'a>(self) -> TryLockReturn<'a, 'context, B, ((), ()), (A0, B), O, Self> + where + 'context: 'a, + { + try_lock_impl!(self, 1) + } + + /// Attempts to lock the second element without blocking. If successful, the + /// tuple becomes unusable until the returned guard is dropped. If the element + /// is already locked, `None` is returned. + #[must_use] + pub fn try_lock_mut_1(&mut self) -> Option<ContextGuard<'_, B::Guard<'_>, ThreadKey>> { + try_lock_mut_impl!(self, 1) + } +} + +impl<'context, A, A0, B: RawLock + Sharable, O> LockingTuple<'context, (A, B), (A0, B), O> { + /// Acquire a shared lock to the second element, and return a new tuple where + /// the second element is inaccessible. + #[must_use] + pub fn read_1<'a>(self) -> ReadReturn<'a, 'context, B, ((), ()), (A0, B), O> + where + 'context: 'a, + { + read_impl!(self, 1) + } + + /// Attempts to acquire a shared lock the second element without blocking, and + /// return a new tuple where the second element is inaccessible. + /// + /// # Errors + /// + /// If the element is already exclusively locked, `Err` is returned with the original + /// tuple. + pub fn try_read_1<'a>(self) -> TryReadReturn<'a, 'context, B, ((), ()), (A0, B), O, Self> + where + 'context: 'a, + { + try_read_impl!(self, 1) + } + + /// Acquire a shared lock to the second element. The tuple becomes unusable + /// until the returned guard is dropped. + #[must_use] + pub fn read_mut_1(&mut self) -> ContextGuard<'_, B::ReadGuard<'_>, ThreadKey> { + read_mut_impl!(self, 1) + } + + /// Attempts to acquire a shared lock the second element without blocking. If + /// successful, the tuple becomes unusable until the returned guard is + /// dropped. If the element is already exclusively locked, `None` is returned. + #[must_use] + pub fn try_read_mut_1(&mut self) -> Option<ContextGuard<'_, B::ReadGuard<'_>, ThreadKey>> { + try_read_mut_impl!(self, 1) + } +} + +impl<'context, A, A0, B, O> LockingTuple<'context, (A, B), (A0, B), O> { + /// Consume the tuple, and return the second element as a new tuple. + #[must_use] + pub fn recurse_1(self) -> RecurseReturn<'context, B, ((), ()), (A0, B), O> { + recurse_impl!(self, 1) + } + + /// Consume the tuple, and return the second element as a locking iterator. + pub fn recurse_1_iter(self) -> RecurseIterReturn<'context, B, (A, ()), (A0, B), O> + where + &'context B: IntoIterator, + { + recurse_iter_impl!(self, 1) + } +} + +impl<'context, A: RawLock + Lockable, B, B0, C, C0, O> + LockingTuple<'context, (A, B, C), (A, B0, C0), O> +{ + /// Lock the first element, and return a new tuple where the first element + /// is inaccessible. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn lock_0<'a>(self) -> LockReturn<'a, 'context, A, ((), B, C), (A, B0, C0), O> + where + 'context: 'a, + { + lock_impl!(self, 0) + } + + /// Lock the first element. The tuple becomes unusable until the returned + /// guard is dropped. + #[must_use] + pub fn lock_mut_0(&mut self) -> ContextGuard<'_, A::Guard<'_>, ThreadKey> { + lock_mut_impl!(self, 0) + } + + /// Attempts to lock the first element without blocking. If successful, the + /// tuple becomes unusable until the returned guard is dropped. If the element + /// is already locked, `None` is returned. + #[must_use] + pub fn try_lock_mut_0(&mut self) -> Option<ContextGuard<'_, A::Guard<'_>, ThreadKey>> { + try_lock_mut_impl!(self, 0) + } +} + +impl<'context, A: RawLock + Sharable, B, B0, C, C0, O> + LockingTuple<'context, (A, B, C), (A, B0, C0), O> +{ + /// Acquire a shared lock to the first element, and return a new tuple where + /// the first element is inaccessible. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn read_0<'a>(self) -> ReadReturn<'a, 'context, A, ((), B, C), (A, B0, C0), O> + where + 'context: 'a, + { + read_impl!(self, 0) + } + + /// Acquire a shared lock to the first element. The tuple becomes unusable + /// until the returned guard is dropped. + #[must_use] + pub fn read_mut_0(&mut self) -> ContextGuard<'_, A::ReadGuard<'_>, ThreadKey> { + read_mut_impl!(self, 0) + } + + /// Attempts to acquire a shared lock the first element without blocking. If + /// successful, the tuple becomes unusable until the returned guard is + /// dropped. If the element is already exclusively locked, `None` is returned. + #[must_use] + pub fn try_read_mut_0(&mut self) -> Option<ContextGuard<'_, A::ReadGuard<'_>, ThreadKey>> { + try_read_mut_impl!(self, 0) + } +} + +impl<'context, A, B, B0, C, C0, O> LockingTuple<'context, (A, B, C), (A, B0, C0), O> { + /// Consume the tuple, and return the first element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_0(self) -> RecurseReturn<'context, A, ((), B, C), (A, B0, C0), O> { + recurse_impl!(self, 0) + } + + /// Consume the tuple, and return the first element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_0_iter(self) -> RecurseIterReturn<'context, A, ((), B, C), (A, B0, C0), O> + where + &'context A: IntoIterator, + { + recurse_iter_impl!(self, 0) + } +} + +impl<'context, A, A0, B: RawLock + Lockable, C, C0, O> + LockingTuple<'context, (A, B, C), (A0, B, C0), O> +{ + /// Lock the second element, and return a new tuple where the first and second + /// elements are inaccessible. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn lock_1<'a>(self) -> LockReturn<'a, 'context, B, ((), (), C), (A0, B, C0), O> + where + 'context: 'a, + { + lock_impl!(self, 1) + } + + /// Lock the second element. The tuple becomes unusable until the returned + /// guard is dropped. + #[must_use] + pub fn lock_mut_1(&mut self) -> ContextGuard<'_, B::Guard<'_>, ThreadKey> { + lock_mut_impl!(self, 1) + } + + /// Attempts to lock the second element without blocking. If successful, the + /// tuple becomes unusable until the returned guard is dropped. If the element + /// is already locked, `None` is returned. + #[must_use] + pub fn try_lock_mut_1(&mut self) -> Option<ContextGuard<'_, B::Guard<'_>, ThreadKey>> { + try_lock_mut_impl!(self, 1) + } +} + +impl<'context, A, A0, B: RawLock + Sharable, C, C0, O> + LockingTuple<'context, (A, B, C), (A0, B, C0), O> +{ + /// Acquire a shared lock to the second element, and return a new tuple where + /// the second element is inaccessible. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn read_1<'a>(self) -> ReadReturn<'a, 'context, B, ((), (), C), (A0, B, C0), O> + where + 'context: 'a, + { + read_impl!(self, 1) + } + + /// Acquire a shared lock to the second element. The tuple becomes unusable + /// until the returned guard is dropped. + #[must_use] + pub fn read_mut_1(&mut self) -> ContextGuard<'_, B::ReadGuard<'_>, ThreadKey> { + read_mut_impl!(self, 1) + } + + /// Attempts to acquire a shared lock the second element without blocking. If + /// successful, the tuple becomes unusable until the returned guard is + /// dropped. If the element is already exclusively locked, `None` is returned. + #[must_use] + pub fn try_read_mut_1(&mut self) -> Option<ContextGuard<'_, B::ReadGuard<'_>, ThreadKey>> { + try_read_mut_impl!(self, 1) + } +} + +impl<'context, A, A0, B, C, C0, O> LockingTuple<'context, (A, B, C), (A0, B, C0), O> { + /// Consume the tuple, and return the second element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_1(self) -> RecurseReturn<'context, B, ((), (), C), (A0, B, C0), O> { + recurse_impl!(self, 1) + } + + /// Consume the tuple, and return the second element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_1_iter(self) -> RecurseIterReturn<'context, B, ((), (), C), (A0, B, C0), O> + where + &'context B: IntoIterator, + { + recurse_iter_impl!(self, 1) + } +} + +impl<'context, A, A0, B, B0, C: RawLock + Lockable, O> + LockingTuple<'context, (A, B, C), (A0, B0, C), O> +{ + /// Lock the third element, and return a new tuple where all elements are + /// inaccessible. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn lock_2<'a>(self) -> LockReturn<'a, 'context, C, ((), (), ()), (A0, B0, C), O> + where + 'context: 'a, + { + lock_impl!(self, 2) + } + + /// Lock the third element. The tuple becomes unusable until the returned + /// guard is dropped. + #[must_use] + pub fn lock_mut_2(&mut self) -> ContextGuard<'_, C::Guard<'_>, ThreadKey> { + lock_mut_impl!(self, 2) + } + + /// Attempts to lock the third element without blocking. If successful, the + /// tuple becomes unusable until the returned guard is dropped. If the element + /// is already locked, `None` is returned. + #[must_use] + pub fn try_lock_mut_2(&mut self) -> Option<ContextGuard<'_, C::Guard<'_>, ThreadKey>> { + try_lock_mut_impl!(self, 2) + } +} + +impl<'context, A, A0, B, B0, C: RawLock + Sharable, O> + LockingTuple<'context, (A, B, C), (A0, B0, C), O> +{ + /// Acquire a shared lock to the third element, and return a new tuple where + /// the third element is inaccessible. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn read_2<'a>(self) -> ReadReturn<'a, 'context, C, ((), (), ()), (A0, B0, C), O> + where + 'context: 'a, + { + read_impl!(self, 2) + } + + /// Acquire a shared lock to the third element. The tuple becomes unusable + /// until the returned guard is dropped. + #[must_use] + pub fn read_mut_2(&mut self) -> ContextGuard<'_, C::ReadGuard<'_>, ThreadKey> { + read_mut_impl!(self, 2) + } + + /// Attempts to acquire a shared lock the third element without blocking. If + /// successful, the tuple becomes unusable until the returned guard is + /// dropped. If the element is already exclusively locked, `None` is returned. + #[must_use] + pub fn try_read_mut_2(&mut self) -> Option<ContextGuard<'_, C::ReadGuard<'_>, ThreadKey>> { + try_read_mut_impl!(self, 2) + } +} + +impl<'context, A, A0, B, B0, C, O> LockingTuple<'context, (A, B, C), (A0, B0, C), O> { + /// Consume the tuple, and return the third element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_2(self) -> RecurseReturn<'context, C, ((), (), ()), (A0, B0, C), O> { + recurse_impl!(self, 2) + } + + /// Consume the tuple, and return the third element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_2_iter(self) -> RecurseIterReturn<'context, C, ((), (), ()), (A0, B0, C), O> + where + &'context C: IntoIterator, + { + recurse_iter_impl!(self, 2) + } +} + +impl<'context, A, B, B0, C, C0, D, D0, O> LockingTuple<'context, (A, B, C, D), (A, B0, C0, D0), O> { + /// Consume the tuple, and return the first element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_0(self) -> RecurseReturn<'context, A, ((), B, C, D), (A, B0, C0, D0), O> { + recurse_impl!(self, 0) + } + + /// Consume the tuple, and return the first element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_0_iter(self) -> RecurseIterReturn<'context, A, ((), B, C, D), (A, B0, C0, D0), O> + where + &'context A: IntoIterator, + { + recurse_iter_impl!(self, 0) + } +} + +impl<'context, A, A0, B, C, C0, D, D0, O> LockingTuple<'context, (A, B, C, D), (A0, B, C0, D0), O> { + /// Consume the tuple, and return the second element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_1(self) -> RecurseReturn<'context, B, ((), (), C, D), (A0, B, C0, D0), O> { + recurse_impl!(self, 1) + } + + /// Consume the tuple, and return the second element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_1_iter( + self, + ) -> RecurseIterReturn<'context, B, ((), (), C, D), (A0, B, C0, D0), O> + where + &'context B: IntoIterator, + { + recurse_iter_impl!(self, 1) + } +} + +impl<'context, A, A0, B, B0, C, D, D0, O> LockingTuple<'context, (A, B, C, D), (A0, B0, C, D0), O> { + /// Consume the tuple, and return the third element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_2(self) -> RecurseReturn<'context, C, ((), (), (), D), (A0, B0, C, D0), O> { + recurse_impl!(self, 2) + } + + /// Consume the tuple, and return the third element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_2_iter( + self, + ) -> RecurseIterReturn<'context, C, ((), (), (), D), (A0, B0, C, D0), O> + where + &'context C: IntoIterator, + { + recurse_iter_impl!(self, 2) + } +} + +impl<'context, A, A0, B, B0, C, C0, D, O> LockingTuple<'context, (A, B, C, D), (A0, B0, C0, D), O> { + /// Consume the tuple, and return the fourth element as a new tuple. + #[must_use] + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_3(self) -> RecurseReturn<'context, D, ((), (), (), ()), (A0, B0, C0, D), O> { + recurse_impl!(self, 3) + } + + /// Consume the tuple, and return the first element as a locking iterator. + // The type is impossible to refactor, and I already wrote this function, so no point in removing it + #[expect(clippy::type_complexity)] + pub fn recurse_3_iter( + self, + ) -> RecurseIterReturn<'context, D, ((), (), (), ()), (A0, B0, C0, D), O> + where + &'context D: IntoIterator, + { + recurse_iter_impl!(self, 3) + } +} |
