summaryrefslogtreecommitdiff
path: root/src/iterator/iterator.rs
blob: 316a27625d6bb16f25c13802dea2531f338158be (plain)
use std::iter::{Enumerate, Fuse, Skip, Take};

use super::{IteratorGuard, LockingIterator};

use crate::{
	lockable::{Lockable, RawLock, Sharable},
	ThreadKey,
};

impl<'l, I> LockingIterator<'l, I> {
	fn with_iterator<M>(self, f: impl FnOnce(I) -> M) -> LockingIterator<'l, M> {
		LockingIterator {
			key: self.key,
			iterator: f(self.iterator),
		}
	}
}

impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Lockable> LockingIterator<'c, L> {
	pub fn lock_next(
		&mut self,
	) -> Option<IteratorGuard<'c, <I as Lockable>::Guard<'c>, ThreadKey>> {
		if let Some(lock) = self.iterator.next() {
			unsafe {
				lock.raw_write();
				let guard = lock.guard();

				Some(IteratorGuard {
					_key: self.key,
					guard,
				})
			}
		} else {
			None
		}
	}

	pub fn lock_last(self) -> Option<IteratorGuard<'c, <I as Lockable>::Guard<'c>, ThreadKey>> {
		self.iterator.last().map(|lock| unsafe {
			lock.raw_write();
			let guard = lock.guard();

			IteratorGuard {
				_key: self.key,
				guard,
			}
		})
	}
}

impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Sharable> LockingIterator<'c, L> {
	pub fn read_next(
		&mut self,
	) -> Option<IteratorGuard<'c, <I as Sharable>::ReadGuard<'c>, ThreadKey>> {
		if let Some(lock) = self.iterator.next() {
			unsafe {
				lock.raw_read();
				let guard = lock.read_guard();

				Some(IteratorGuard {
					_key: self.key,
					guard,
				})
			}
		} else {
			None
		}
	}

	pub fn read_last(self) -> Option<IteratorGuard<'c, <I as Sharable>::ReadGuard<'c>, ThreadKey>> {
		self.iterator.last().map(|lock| unsafe {
			lock.raw_read();
			let guard = lock.read_guard();

			IteratorGuard {
				_key: self.key,
				guard,
			}
		})
	}
}

impl<'l, L: Iterator> LockingIterator<'l, L> {
	pub fn skip_next(&mut self) -> Option<L::Item> {
		self.iterator.next()
	}

	pub fn skip_mut(&mut self, n: usize) {
		for _ in 0..n {
			self.iterator.next();
		}
	}

	#[must_use]
	pub fn size_hint(&self) -> (usize, Option<usize>) {
		self.iterator.size_hint()
	}

	#[must_use]
	pub fn enumerate(self) -> LockingIterator<'l, Enumerate<L>> {
		self.with_iterator(Iterator::enumerate)
	}

	#[must_use]
	pub fn skip(self, n: usize) -> LockingIterator<'l, Skip<L>> {
		self.with_iterator(|i| i.skip(n))
	}

	#[must_use]
	pub fn take(self, n: usize) -> LockingIterator<'l, Take<L>> {
		self.with_iterator(|i| i.take(n))
	}

	#[must_use]
	pub fn fuse(self) -> LockingIterator<'l, Fuse<L>> {
		self.with_iterator(Iterator::fuse)
	}
}