summaryrefslogtreecommitdiff
path: root/src/iterator/tuple.rs
blob: 855cdc785b033ab0c67ccc6b8807c5b3211a0509 (plain)
use std::marker::PhantomData;

use crate::{
	iterator::{IteratorGuard, LockingTuple},
	lockable::{Lockable, RawLock},
	ThreadKey,
};

impl<'c, A, B> LockingTuple<'c, A, B> {
	const fn transmute<C>(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, <Guarded as Lockable>::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, <A as Lockable>::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)
	}
}