seekable_iterator/
pooled.rs

1use core::error::Error;
2use core::fmt::{Display, Formatter, Result as FmtResult};
3
4#[cfg(feature = "lender")]
5use crate::lender_adapter::PooledLenderAdapter;
6#[cfg(feature = "lending-iterator")]
7use crate::lending_iterator_adapter::PooledLendingIteratorAdapter;
8
9
10/// A `PooledIterator` is similar to a lending iterator (which can lend one item at a time), but
11/// can make use of a buffer pool to lend out multiple items at a time.
12///
13/// Implementations may or may not be threadsafe. Even if an implementation is threadsafe,
14/// items newly-added to the backing collection of the iterator may or may not be seen
15/// immediately by other threads.
16///
17/// [`FusedIterator`]: core::iter::FusedIterator
18pub trait PooledIterator {
19    /// The item of this iterator, which likely has a nontrivial drop implementation that returns
20    /// a buffer to the iterator's buffer pool.
21    type Item;
22
23    /// Move the iterator one position forwards, and return the entry at that position.
24    /// Returns `None` if the iterator was at the last entry.
25    ///
26    /// May need to wait for a buffer to become available.
27    ///
28    /// # Potential Panics or Deadlocks
29    /// If `self.buffer_pool_size() == 0`, then this method is permitted to panic or deadlock.
30    /// This method may also panic or cause a deadlock if no buffers are currently available, and
31    /// the current thread needs to make progress in order to release a buffer.
32    ///
33    /// If it is possible for a different thread to make progress and make a buffer available,
34    /// this method should not panic or deadlock.
35    fn next(&mut self) -> Option<Self::Item>;
36
37    /// If a buffer is available, move the iterator one position forwards, and return the entry at
38    /// that position. Returns `Ok(None)` if the iterator was at the last entry.
39    ///
40    /// # Errors
41    /// Returns an error if no buffers were available.
42    fn try_next(&mut self) -> Result<Option<Self::Item>, OutOfBuffers>;
43
44    /// Get the total number of buffers in the buffer pool, including buffers that are
45    /// currently in use.
46    #[must_use]
47    fn buffer_pool_size(&self) -> usize;
48
49    /// Get the number of buffers that are currently available.
50    ///
51    /// In multithreaded scenarios, the returned value could change at any time.
52    #[must_use]
53    fn available_buffers(&self) -> usize;
54
55    /// Convert the `PooledIterator` into a [`lender::Lender`] lending iterator which only uses
56    /// one buffer at a time.
57    ///
58    /// The seekability and access to cursor methods are preserved, though none of the
59    /// `Cursor*Iterator` or `Seekable*Iterator` traits are implemented for the adaptor, in order
60    /// to avoid conflicts with the `next()` method name.
61    ///
62    /// # Potential Panics or Deadlocks
63    /// If `self.buffer_pool_size() == 0`, then methods of the returned iterator might panic or
64    /// deadlock.
65    #[cfg(feature = "lender")]
66    #[inline]
67    #[must_use]
68    fn into_lender(self) -> PooledLenderAdapter<Self> where Self: Sized {
69        PooledLenderAdapter::new(self)
70    }
71
72    /// Convert the `PooledIterator` into a [`lending_iterator::LendingIterator`] which only uses
73    /// one buffer at a time.
74    ///
75    /// The seekability and access to cursor methods are preserved, though none of the
76    /// `Cursor*Iterator` or `Seekable*Iterator` traits are implemented for the adaptor, in order
77    /// to avoid conflicts with the `next()` method name.
78    ///
79    /// # Potential Panics or Deadlocks
80    /// If `self.buffer_pool_size() == 0`, then methods of the returned iterator might panic or
81    /// deadlock.
82    #[cfg(feature = "lending-iterator")]
83    #[inline]
84    #[must_use]
85    fn into_lending_iterator(self) -> PooledLendingIteratorAdapter<Self> where Self: Sized {
86        PooledLendingIteratorAdapter::new(self)
87    }
88}
89
90/// An error that may be returned if no buffer pools were available in a [`PooledIterator`],
91/// instead of waiting for a buffer to become available.
92#[derive(Debug, Clone, Copy)]
93pub struct OutOfBuffers;
94
95impl Display for OutOfBuffers {
96    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
97        write!(
98            f,
99            "a pooled iterator operation was not performed because there were no buffers available",
100        )
101    }
102}
103
104impl Error for OutOfBuffers {}