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 {}