1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
use super::atomic_counter::AtomicCounter;
use crate::next::{Next, NextChunk};
/// Trait defining a set of concurrent iterators which internally uses an atomic counter of elements to be yielded.
///
/// Note that every `A: AtomicIter` also implements `ConcurrentIter`.
pub trait AtomicIter<T: Send + Sync>: Send + Sync {
    /// Returns a reference to the underlying advanced item counter.
    fn counter(&self) -> &AtomicCounter;
    /// Progresses the atomic counter by `number_to_fetch` elements and returns the beginning index of the elements to be fetched.
    /// Returns None if the iterator is terminated and there are no more elements to be fetched.
    ///
    /// Note that this method must only return when the calling thread is allowed to fetch elements.
    fn progress_and_get_begin_idx(&self, number_to_fetch: usize) -> Option<usize>;
    /// Returns the `item_idx`-th item that the iterator yields; returns None if the iterator completes before.
    fn get(&self, item_idx: usize) -> Option<T>;
    /// Returns the next item that the iterator yields; returns None if the iteration has completed.
    #[inline(always)]
    fn fetch_one(&self) -> Option<Next<T>> {
        let idx = self.counter().fetch_and_increment();
        self.get(idx).map(|value| Next { idx, value })
    }
    /// Returns an iterator of the next `n` **consecutive items** that the iterator yields.
    /// It might return an iterator of less or no items if the iteration does not have sufficient elements left.
    fn fetch_n(&self, n: usize) -> Option<NextChunk<T, impl ExactSizeIterator<Item = T>>>;
    /// Skips all remaining elements of the iterator and assumes that the end of the iterator is reached.
    ///
    /// This method establishes a very primitive, convenient and critical communication among threads for search scenarios with an early exit condition.
    /// Assume, for instance, that we are trying to `find` an element satisfying a predicate using multiple threads.
    /// Whenever a threads finds a match, it can call this method and return the found value.
    /// Then, when the other threads try to pull next element from the iterator, they will observe that the iterator has ended.
    /// Therefore, they will as well return early as desired.
    fn early_exit(&self);
}
/// An atomic counter based iterator with exactly known initial length.
pub trait AtomicIterWithInitialLen<T: Send + Sync>: AtomicIter<T> {
    /// Returns the initial length of the atomic iterator.
    fn initial_len(&self) -> usize;
}