summaryrefslogtreecommitdiff
path: root/src/context/iterator.rs
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2026-08-26 20:46:31 -0400
committerMica White <botahamec@outlook.com>2026-08-26 20:46:31 -0400
commit55b3a2425b242fbc5c6e471f220eeb8b949e8751 (patch)
tree5ceb7910b60cc7331024b7ce1d49ec259e0302a8 /src/context/iterator.rs
parent6f6e030ea7edb9d155ebf21b5d42936c20801b50 (diff)
Add tests
Diffstat (limited to 'src/context/iterator.rs')
-rw-r--r--src/context/iterator.rs695
1 files changed, 695 insertions, 0 deletions
diff --git a/src/context/iterator.rs b/src/context/iterator.rs
new file mode 100644
index 0000000..cc3bd7c
--- /dev/null
+++ b/src/context/iterator.rs
@@ -0,0 +1,695 @@
+use std::{
+ iter::{Fuse, Peekable, Skip, Take},
+ marker::PhantomData,
+};
+
+use super::{ContextGuard, LockingIterator};
+
+use crate::{
+ context::LockingTuple,
+ lockable::{Lockable, RawLock, Sharable},
+ ThreadKey,
+};
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum TryLockNextError {
+ FinishedIteration,
+ WouldBlock,
+}
+
+impl<'l, I, O> LockingIterator<'l, I, O> {
+ fn with_iterator<M>(self, f: impl FnOnce(I) -> M) -> LockingIterator<'l, M, O> {
+ LockingIterator {
+ key: self.key,
+ iterator: f(self.iterator),
+ outer: self.outer,
+ }
+ }
+
+ /// Exit out of the current scope of the locking iterator into the parent.
+ ///
+ /// After using one the recurse methods, it is possible to regain access to
+ /// the parent by exiting out of the scope of the child. Doing this will make
+ /// it impossible to re-enter this scope again.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = ([Mutex::new(1), Mutex::new(2), Mutex::new(3)], Mutex::new(true));
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let tuple = ctx.tuple(key);
+ /// let mut iter = tuple.recurse_0_iter();
+ ///
+ /// let mut sum = 0;
+ /// while let Some(item) = iter.lock_next() {
+ /// sum += **item;
+ /// }
+ ///
+ /// let tuple = iter.exit();
+ /// let (should_assert, _) = tuple.lock_1();
+ /// if **should_assert {
+ /// assert_eq!(sum, 6);
+ /// }
+ /// ```
+ pub fn exit(self) -> O {
+ self.outer
+ }
+}
+
+impl<'c, L: Iterator<Item = I>, I: IntoIterator, O> LockingIterator<'c, L, O> {
+ /// Create a new `LockingIterator` based on the next element in the iterator.
+ ///
+ /// If a list contains a list of locks, then this method can be used to
+ /// recurse into the next element of the list. To go back to the parent scope,
+ /// use [`LockingIterator::exit`] on the new list.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [
+ /// [Mutex::new(1), Mutex::new(2), Mutex::new(3)],
+ /// [Mutex::new(4), Mutex::new(5), Mutex::new(6)],
+ /// ];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// let mut sums = Vec::new();
+ /// while let Some(mut list) = iter.recurse_next() {
+ /// let mut sum = 0;
+ /// while let Some(item) = list.lock_next() {
+ /// sum += **item;
+ /// }
+ /// sums.push(sum);
+ /// iter = list.exit();
+ /// }
+ ///
+ /// assert_eq!(sums, vec![6, 15]);
+ /// ```
+ pub fn recurse_next(
+ mut self,
+ ) -> Option<LockingIterator<'c, <I as IntoIterator>::IntoIter, Self>> {
+ if let Some(iterator) = self.iterator.next() {
+ Some(LockingIterator {
+ key: self.key,
+ iterator: iterator.into_iter(),
+ outer: self,
+ })
+ } else {
+ None
+ }
+ }
+
+ /// Create a new `LockingIterator` based on the next element in the iterator.
+ ///
+ /// If a list contains a list of locks, then this method can be used to
+ /// recurse into the next element of the list. To go back to the parent scope,
+ /// use [`LockingIterator::exit`] on the new list.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [
+ /// [Mutex::new(1), Mutex::new(2), Mutex::new(3)],
+ /// [Mutex::new(4), Mutex::new(5), Mutex::new(6)],
+ /// ];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let iter = ctx.iter(key);
+ ///
+ /// let mut list = iter.recurse_last().unwrap();
+ /// let mut sum = 0;
+ /// while let Some(item) = list.lock_next() {
+ /// sum += **item;
+ /// }
+ ///
+ /// assert_eq!(sum, 15);
+ /// ```
+ pub fn recurse_last(self) -> Option<LockingIterator<'c, <I as IntoIterator>::IntoIter, O>> {
+ if let Some(iterator) = self.iterator.last() {
+ Some(LockingIterator {
+ key: self.key,
+ iterator: iterator.into_iter(),
+ outer: self.outer,
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'c, L: Iterator<Item = &'c T>, T: 'c, O> LockingIterator<'c, L, O> {
+ /// Create a new `LockingIterator` based on the next element in the iterator.
+ ///
+ /// If a list contains a list of locks, then this method can be used to
+ /// recurse into the next element of the list. To go back to the parent scope,
+ /// use [`LockingIterator::exit`] on the new list.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [
+ /// (Mutex::new(true), Mutex::new(1)),
+ /// (Mutex::new(false), Mutex::new(2)),
+ /// (Mutex::new(true), Mutex::new(3)),
+ /// ];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// let mut sum = 0;
+ /// while let Some(tuple) = iter.recurse_next_tuple() {
+ /// let (should_count, mut tuple) = tuple.lock_0();
+ /// if **should_count {
+ /// let num = tuple.lock_mut_1();
+ /// sum += **num;
+ /// }
+ /// iter = tuple.exit();
+ /// }
+ ///
+ /// assert_eq!(sum, 4);
+ /// ```
+ pub fn recurse_next_tuple(mut self) -> Option<LockingTuple<'c, T, T, Self>> {
+ if let Some(tuple) = self.iterator.next() {
+ Some(LockingTuple {
+ key: self.key,
+ _lockable: PhantomData,
+ tuple,
+ outer: self,
+ })
+ } else {
+ None
+ }
+ }
+
+ /// Create a new `LockingIterator` based on the next element in the iterator.
+ ///
+ /// If a list contains a list of locks, then this method can be used to
+ /// recurse into the next element of the list. To go back to the parent scope,
+ /// use [`LockingIterator::exit`] on the new list.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [
+ /// (Mutex::new(true), Mutex::new(1)),
+ /// (Mutex::new(false), Mutex::new(2)),
+ /// (Mutex::new(true), Mutex::new(3)),
+ /// ];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let iter = ctx.iter(key);
+ ///
+ /// let tuple = iter.recurse_last_tuple().unwrap();
+ /// let (should_count, mut tuple) = tuple.lock_0();
+ /// if **should_count {
+ /// let num = tuple.lock_mut_1();
+ /// assert_eq!(**num, 3);
+ /// } else {
+ /// panic!();
+ /// }
+ /// ```
+ pub fn recurse_last_tuple(self) -> Option<LockingTuple<'c, T, T, O>> {
+ if let Some(tuple) = self.iterator.last() {
+ Some(LockingTuple {
+ key: self.key,
+ _lockable: PhantomData,
+ tuple,
+ outer: self.outer,
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Lockable, O> LockingIterator<'c, L, O> {
+ /// Advances the iterator, locking the next element and returning a guard to
+ /// the inner data.
+ ///
+ /// Returns `None` when iteration is finished. Individual iterator
+ /// implementations may choose to resume iteration, and so calling `next()`
+ /// again may or may not eventually start returning `Some(Item)` again at some
+ /// point.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(3), Mutex::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// let mut sum = 0;
+ /// while let Some(item) = iter.lock_next() {
+ /// sum += **item;
+ /// }
+ ///
+ /// assert_eq!(sum, 12);
+ /// ```
+ pub fn lock_next(&mut self) -> Option<ContextGuard<'c, <I as Lockable>::Guard<'c>, ThreadKey>> {
+ if let Some(lock) = self.iterator.next() {
+ unsafe {
+ lock.raw_write();
+ let guard = lock.guard();
+
+ Some(ContextGuard {
+ _key: self.key,
+ guard,
+ })
+ }
+ } else {
+ None
+ }
+ }
+
+ /// Consumes the iterator, returning the last element, without locking any
+ /// other elements.
+ ///
+ /// This method will evaluate the iterator until it returns `None`. While
+ /// doing so, it keeps track of the current element. After `None` is returned,
+ /// `lock_last()` will then lock the last element it saw and return the
+ /// lock's data.
+ ///
+ /// # Panics
+ ///
+ /// This function might panic if the iterator is infinite.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(3), Mutex::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let iter = ctx.iter(key);
+ ///
+ /// let last = iter.lock_last().unwrap();
+ /// assert_eq!(**last, 8);
+ /// ```
+ pub fn lock_last(self) -> Option<ContextGuard<'c, <I as Lockable>::Guard<'c>, ThreadKey>> {
+ self.iterator.last().map(|lock| unsafe {
+ lock.raw_write();
+ let guard = lock.guard();
+
+ ContextGuard {
+ _key: self.key,
+ guard,
+ }
+ })
+ }
+}
+
+impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Lockable, O>
+ LockingIterator<'c, Peekable<L>, O>
+{
+ /// Attempts to lock the next element and returning a guard to
+ /// the inner data.
+ ///
+ /// # Errors
+ ///
+ /// Returns `Err(TryLockNextError::FinishedIteration)` when iteration is
+ /// finished. Individual iterator implementations may choose to resume
+ /// iteration, and so calling `next()` again may or may not eventually start
+ /// returning `Some(Item)` again at some point.
+ ///
+ /// Returns `Err(TryLockNextError::WouldBlock)` if the next lock in the
+ /// iterator is already locked. This will not advance the iterator.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ /// use happylock::context::iterator::TryLockNextError;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(3), Mutex::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key).peekable();
+ ///
+ /// let mut sum = 0;
+ /// loop {
+ /// match iter.try_lock_next() {
+ /// Ok(item) => sum += **item,
+ /// Err(TryLockNextError::WouldBlock) => continue,
+ /// Err(TryLockNextError::FinishedIteration) => break,
+ /// }
+ /// }
+ ///
+ /// assert_eq!(sum, 12);
+ /// ```
+ pub fn try_lock_next(
+ &mut self,
+ ) -> Result<ContextGuard<'c, <I as Lockable>::Guard<'c>, ThreadKey>, TryLockNextError> {
+ if let Some(lock) = self.iterator.peek().copied() {
+ unsafe {
+ if lock.raw_try_write() {
+ // safety: we just saw that there is a valid value
+ let lock = self.iterator.next().unwrap_unchecked();
+ let guard = lock.guard();
+
+ Ok(ContextGuard {
+ _key: self.key,
+ guard,
+ })
+ } else {
+ Err(TryLockNextError::WouldBlock)
+ }
+ }
+ } else {
+ Err(TryLockNextError::FinishedIteration)
+ }
+ }
+}
+
+impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Sharable, O> LockingIterator<'c, L, O> {
+ /// Advances the iterator, acquiring a shared lock to the next element and
+ /// returning a guard to the inner data.
+ ///
+ /// Returns `None` when iteration is finished. Individual iterator
+ /// implementations may choose to resume iteration, and so calling `next()`
+ /// again may or may not eventually start returning `Some(Item)` again at some
+ /// point.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{RwLock, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [RwLock::new(1), RwLock::new(3), RwLock::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// let mut sum = 0;
+ /// while let Some(item) = iter.read_next() {
+ /// sum += **item;
+ /// }
+ ///
+ /// assert_eq!(sum, 12);
+ /// ```
+ pub fn read_next(
+ &mut self,
+ ) -> Option<ContextGuard<'c, <I as Sharable>::ReadGuard<'c>, ThreadKey>> {
+ if let Some(lock) = self.iterator.next() {
+ unsafe {
+ lock.raw_read();
+ let guard = lock.read_guard();
+
+ Some(ContextGuard {
+ _key: self.key,
+ guard,
+ })
+ }
+ } else {
+ None
+ }
+ }
+
+ /// Consumes the iterator, returning the last element with readonly access,
+ /// without locking any other elements.
+ ///
+ /// This method will evaluate the iterator until it returns `None`. While
+ /// doing so, it keeps track of the current element. After `None` is returned,
+ /// `lock_last()` will then lock the last element it saw and return the
+ /// lock's data.
+ ///
+ /// # Panics
+ ///
+ /// This function might panic if the iterator is infinite.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{RwLock, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [RwLock::new(1), RwLock::new(3), RwLock::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let iter = ctx.iter(key);
+ ///
+ /// let last = iter.read_last().unwrap();
+ /// assert_eq!(**last, 8);
+ /// ```
+ pub fn read_last(self) -> Option<ContextGuard<'c, <I as Sharable>::ReadGuard<'c>, ThreadKey>> {
+ self.iterator.last().map(|lock| unsafe {
+ lock.raw_read();
+ let guard = lock.read_guard();
+
+ ContextGuard {
+ _key: self.key,
+ guard,
+ }
+ })
+ }
+}
+
+impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Sharable, O>
+ LockingIterator<'c, Peekable<L>, O>
+{
+ /// Attempts to acquire a shared lock the next element and returning a guard
+ /// to the inner data.
+ ///
+ /// # Errors
+ ///
+ /// Returns `Err(TryLockNextError::FinishedIteration)` when iteration is
+ /// finished. Individual iterator implementations may choose to resume
+ /// iteration, and so calling `next()` again may or may not eventually start
+ /// returning `Some(Item)` again at some point.
+ ///
+ /// Returns `Err(TryLockNextError::WouldBlock)` if the next lock in the
+ /// iterator is already locked. This will not advance the iterator.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{RwLock, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ /// use happylock::context::iterator::TryLockNextError;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [RwLock::new(1), RwLock::new(3), RwLock::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key).peekable();
+ ///
+ /// let mut sum = 0;
+ /// loop {
+ /// match iter.try_read_next() {
+ /// Ok(item) => sum += **item,
+ /// Err(TryLockNextError::WouldBlock) => continue,
+ /// Err(TryLockNextError::FinishedIteration) => break,
+ /// }
+ /// }
+ ///
+ /// assert_eq!(sum, 12);
+ /// ```
+ pub fn try_read_next(
+ &mut self,
+ ) -> Result<ContextGuard<'c, <I as Sharable>::ReadGuard<'c>, ThreadKey>, TryLockNextError> {
+ if let Some(lock) = self.iterator.peek().copied() {
+ unsafe {
+ if lock.raw_try_read() {
+ // safety: we just saw that there is a valid value
+ let lock = self.iterator.next().unwrap_unchecked();
+ let guard = lock.read_guard();
+
+ Ok(ContextGuard {
+ _key: self.key,
+ guard,
+ })
+ } else {
+ Err(TryLockNextError::WouldBlock)
+ }
+ }
+ } else {
+ Err(TryLockNextError::FinishedIteration)
+ }
+ }
+}
+
+impl<'l, L: Iterator, O> LockingIterator<'l, L, O> {
+ /// Advances the iterator, without locking the next element in the iterator.
+ ///
+ /// Returns `false` when iteration is finished. Individual iterator
+ /// implementations may choose to resume iteration, and so calling
+ /// `skip_next()` again may or may not eventually start returning `true` again
+ /// at some point.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(3), Mutex::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// iter.skip_next();
+ /// assert!(iter.lock_next().is_some_and(|v| **v == 3));
+ /// ```
+ pub fn skip_next(&mut self) -> bool {
+ self.iterator.next().is_some()
+ }
+
+ /// Advances the iterator, skipping `n` elements without locking.
+ ///
+ /// See [`Iterator::skip`] for more information.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(3), Mutex::new(8)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// iter.skip_mut(2);
+ /// assert!(iter.lock_next().is_some_and(|v| **v == 8));
+ /// ```
+ pub fn skip_mut(&mut self, n: usize) {
+ for _ in 0..n {
+ self.iterator.next();
+ }
+ }
+
+ /// Returns the bounds on the remaining length of the iterator.
+ ///
+ /// See [`Iterator::size_hint`] for more information.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(2), Mutex::new(3)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key);
+ ///
+ /// assert_eq!((3, Some(3)), iter.size_hint());
+ /// let _ = iter.skip_next();
+ /// assert_eq!((2, Some(2)), iter.size_hint());
+ /// ```
+ #[must_use]
+ pub fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iterator.size_hint()
+ }
+
+ /// Creates a new [`LockingIterator`] that skips the first `n` elements.
+ ///
+ /// Unlike `skip_next` or `skip_mut`, this method does not modify the iterator
+ /// in place. Instead, it returns a new iterator which skips the first `n`
+ /// elements.
+ ///
+ /// See [`Iterator::skip`] for more information.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(2), Mutex::new(3)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key).skip(2);
+ ///
+ /// assert!(iter.lock_next().is_some_and(|v| **v == 3));
+ /// assert!(iter.lock_next().is_none());
+ /// ```
+ #[must_use]
+ pub fn skip(self, n: usize) -> LockingIterator<'l, Skip<L>, O> {
+ self.with_iterator(|i| i.skip(n))
+ }
+
+ /// Creates a new [`LockingIterator`] that yields only the first `n` elements,
+ /// or fewer if the iterator ends sooner.
+ ///
+ /// See [`Iterator::take`] for more information.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use happylock::{Mutex, ThreadKey};
+ /// use happylock::collection::OwnedLockCollection;
+ ///
+ /// let key = ThreadKey::get().unwrap();
+ /// let data = [Mutex::new(1), Mutex::new(2), Mutex::new(3)];
+ /// let locks = OwnedLockCollection::new(data);
+ /// let mut ctx = locks.context();
+ /// let mut iter = ctx.iter(key).take(2);
+ ///
+ /// assert!(iter.lock_next().is_some_and(|v| **v == 1));
+ /// assert!(iter.lock_next().is_some_and(|v| **v == 2));
+ /// assert!(iter.lock_next().is_none());
+ /// ```
+ #[must_use]
+ pub fn take(self, n: usize) -> LockingIterator<'l, Take<L>, O> {
+ self.with_iterator(|i| i.take(n))
+ }
+
+ /// Creates a new [`LockingIterator`] that ends after the first `None`
+ ///
+ /// See [`Iterator::fuse`] for more information
+ #[must_use]
+ pub fn fuse(self) -> LockingIterator<'l, Fuse<L>, O> {
+ self.with_iterator(Iterator::fuse)
+ }
+
+ /// Creates a new [`LockingIterator`] which has access to the
+ /// [`try_lock_next`] and/or [`try_read_next`] methods.
+ ///
+ /// See [`Iterator::peekable`] for more information
+ ///
+ /// [`try_lock_next`]: `LockingIterator::try_lock_next`
+ /// [`try_read_next`]: `LockingIterator::try_read_next`
+ #[must_use]
+ pub fn peekable(self) -> LockingIterator<'l, Peekable<L>, O> {
+ self.with_iterator(Iterator::peekable)
+ }
+}