use std::marker::PhantomData; use crate::{ iterator::{IteratorGuard, LockingTuple}, lockable::{Lockable, RawLock}, ThreadKey, }; impl<'c, A, B> LockingTuple<'c, A, B> { const fn transmute(self) -> LockingTuple<'c, C, B> { LockingTuple { _lockable: PhantomData, key: self.key, tuple: self.tuple, } } } macro_rules! lock_impl { ($self: expr, $field: tt) => { unsafe { $self.tuple.$field.raw_write(); ( IteratorGuard { _key: &$self.key, guard: $self.tuple.$field.guard(), }, $self.transmute(), ) } }; } macro_rules! recurse_impl { ($self: expr, $field: tt) => { LockingTuple { _lockable: PhantomData, key: $self.key, tuple: &$self.tuple.$field, } }; } type LockReturn<'a, 'context, Guarded, L, C> = ( IteratorGuard<'a, ::Guard<'a>, ThreadKey>, LockingTuple<'context, L, C>, ); impl<'context, A: RawLock + Lockable> LockingTuple<'context, (A,), (A,)> { #[must_use] pub fn lock_0<'a>(self) -> LockReturn<'a, 'context, A, ((),), (A,)> where 'context: 'a, { lock_impl!(self, 0) } } impl<'context, A> LockingTuple<'context, (A,), (A,)> { #[must_use] pub const fn recurse_0(self) -> LockingTuple<'context, A, A> { recurse_impl!(self, 0) } } impl<'context, A: RawLock + Lockable, B, B0> LockingTuple<'context, (A, B), (A, B0)> { #[must_use] pub fn lock_0<'a>(self) -> LockReturn<'a, 'context, A, ((), B), (A, B0)> where 'context: 'a, { lock_impl!(self, 0) } } impl<'context, A, B, B0> LockingTuple<'context, (A, B), (A, B0)> { #[must_use] pub const fn recurse_0(self) -> LockingTuple<'context, A, A> { recurse_impl!(self, 0) } } impl<'context, A: Lockable + RawLock, B> LockingTuple<'context, (A, B), (A, B)> { #[must_use] pub fn lock_and_recurse<'a>( self, ) -> ( IteratorGuard<'a, ::Guard<'a>, ThreadKey>, LockingTuple<'context, B, B>, ) where 'context: 'a, { unsafe { self.tuple.0.raw_write(); ( IteratorGuard { _key: self.key, guard: self.tuple.0.guard(), }, LockingTuple { _lockable: PhantomData, key: self.key, tuple: &self.tuple.1, }, ) } } } impl<'context, A, A0, B: RawLock + Lockable> LockingTuple<'context, (A, B), (A0, B)> { #[must_use] pub fn lock_1<'a>(self) -> LockReturn<'a, 'context, B, ((), ()), (A0, B)> where 'context: 'a, { lock_impl!(self, 1) } } impl<'context, A, A0, B> LockingTuple<'context, (A, B), (A0, B)> { #[must_use] pub const fn recurse_1(self) -> LockingTuple<'context, B, B> { recurse_impl!(self, 1) } } impl<'context, A: RawLock + Lockable, B, B0, C, C0> LockingTuple<'context, (A, B, C), (A, B0, C0)> { #[must_use] pub fn lock_0<'a>(self) -> LockReturn<'a, 'context, A, ((), B, C), (A, B0, C0)> where 'context: 'a, { lock_impl!(self, 0) } } impl<'context, A, B, B0, C, C0> LockingTuple<'context, (A, B, C), (A, B0, C0)> { #[must_use] pub const fn recurse_0(self) -> LockingTuple<'context, A, A> { recurse_impl!(self, 0) } } impl<'context, A, A0, B: RawLock + Lockable, C, C0> LockingTuple<'context, (A, B, C), (A0, B, C0)> { #[must_use] pub fn lock_1<'a>(self) -> LockReturn<'a, 'context, B, ((), (), C), (A0, B, C0)> where 'context: 'a, { lock_impl!(self, 1) } } impl<'context, A, A0, B, C, C0> LockingTuple<'context, (A, B, C), (A0, B, C0)> { #[must_use] pub const fn recurse_1(self) -> LockingTuple<'context, B, B> { recurse_impl!(self, 1) } } impl<'context, A, A0, B, B0, C: RawLock + Lockable> LockingTuple<'context, (A, B, C), (A0, B0, C)> { #[must_use] pub fn lock_2<'a>(self) -> LockReturn<'a, 'context, C, ((), (), ()), (A0, B0, C)> where 'context: 'a, { lock_impl!(self, 2) } } impl<'context, A, A0, B, B0, C> LockingTuple<'context, (A, B, C), (A0, B0, C)> { #[must_use] pub const fn recurse_2(self) -> LockingTuple<'context, C, C> { recurse_impl!(self, 2) } } impl<'context, A, B, B0, C, C0, D, D0> LockingTuple<'context, (A, B, C, D), (A, B0, C0, D0)> { #[must_use] pub const fn recurse_0(self) -> LockingTuple<'context, A, A> { recurse_impl!(self, 0) } } impl<'context, A, A0, B, C, C0, D, D0> LockingTuple<'context, (A, B, C, D), (A0, B, C0, D0)> { #[must_use] pub const fn recurse_1(self) -> LockingTuple<'context, B, B> { recurse_impl!(self, 1) } } impl<'context, A, A0, B, B0, C, D, D0> LockingTuple<'context, (A, B, C, D), (A0, B0, C, D0)> { #[must_use] pub const fn recurse_2(self) -> LockingTuple<'context, C, C> { recurse_impl!(self, 2) } } impl<'context, A, A0, B, B0, C, C0, D> LockingTuple<'context, (A, B, C, D), (A0, B0, C0, D)> { #[must_use] pub const fn recurse_3(self) -> LockingTuple<'context, D, D> { recurse_impl!(self, 3) } }