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 may panic or deadlock.
30 fn next(&mut self) -> Option<Self::Item>;
31
32 /// If a buffer is available, move the iterator one position forwards, and return the entry at
33 /// that position. Returns `Ok(None)` if the iterator was at the last entry.
34 ///
35 /// # Errors
36 /// Returns an error if no buffers were available.
37 fn try_next(&mut self) -> Result<Option<Self::Item>, OutOfBuffers>;
38
39 /// Get the total number of buffers in the buffer pool, including buffers that are
40 /// currently in use.
41 #[must_use]
42 fn buffer_pool_size(&self) -> usize;
43
44 /// Get the number of buffers that are currently available.
45 ///
46 /// In multithreaded scenarios, the returned value could change at any time.
47 #[must_use]
48 fn available_buffers(&self) -> usize;
49
50 /// Convert the `PooledIterator` into a [`lender::Lender`] lending iterator which only uses
51 /// one buffer at a time.
52 ///
53 /// The seekability and access to cursor methods are preserved, though none of the
54 /// `Cursor*Iterator` or `Seekable*Iterator` traits are implemented for the adaptor, in order
55 /// to avoid conflicts with the `next()` method name.
56 ///
57 /// # Potential Panics or Deadlocks
58 /// If `self.buffer_pool_size() == 0`, then methods of the returned iterator might panic or
59 /// deadlock.
60 #[cfg(feature = "lender")]
61 #[inline]
62 #[must_use]
63 fn into_lender(self) -> PooledLenderAdapter<Self> where Self: Sized {
64 PooledLenderAdapter::new(self)
65 }
66
67 /// Convert the `PooledIterator` into a [`lending_iterator::LendingIterator`] which only uses
68 /// one buffer at a time.
69 ///
70 /// The seekability and access to cursor methods are preserved, though none of the
71 /// `Cursor*Iterator` or `Seekable*Iterator` traits are implemented for the adaptor, in order
72 /// to avoid conflicts with the `next()` method name.
73 ///
74 /// # Potential Panics or Deadlocks
75 /// If `self.buffer_pool_size() == 0`, then methods of the returned iterator might panic or
76 /// deadlock.
77 #[cfg(feature = "lending-iterator")]
78 #[inline]
79 #[must_use]
80 fn into_lending_iterator(self) -> PooledLendingIteratorAdapter<Self> where Self: Sized {
81 PooledLendingIteratorAdapter::new(self)
82 }
83}
84
85/// An error that may be returned if no buffer pools were available in a [`PooledIterator`],
86/// instead of waiting for a buffer to become available.
87#[derive(Debug, Clone, Copy)]
88pub struct OutOfBuffers;
89
90impl Display for OutOfBuffers {
91 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
92 write!(
93 f,
94 "a pooled iterator operation was not performed because there were no buffers available",
95 )
96 }
97}
98
99impl Error for OutOfBuffers {}