use std::io;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) struct RingId(u64);
impl RingId {
pub(crate) fn next() -> Self {
static NEXT: AtomicU64 = AtomicU64::new(1);
Self(NEXT.fetch_add(1, Ordering::Relaxed))
}
}
#[derive(Debug)]
pub(crate) struct Accounting {
ring_id: RingId,
next_user_data: usize,
outstanding: usize,
registered_files: u32,
registered_buffers: u32,
}
impl Accounting {
pub(crate) fn new() -> Self {
Self {
ring_id: RingId::next(),
next_user_data: 0,
outstanding: 0,
registered_files: 0,
registered_buffers: 0,
}
}
pub(crate) fn ring_id(&self) -> RingId {
self.ring_id
}
pub(crate) fn outstanding(&self) -> usize {
self.outstanding
}
pub(crate) fn reserve_user_data(&mut self) -> io::Result<usize> {
let id = self.next_user_data;
self.next_user_data = id
.checked_add(1)
.ok_or_else(|| io::Error::other("IoRing operation identity space exhausted"))?;
self.outstanding += 1;
Ok(id)
}
pub(crate) fn record_completion(&mut self) {
self.outstanding = self.outstanding.saturating_sub(1);
}
pub(crate) fn cancel_reservation(&mut self) {
self.outstanding = self.outstanding.saturating_sub(1);
}
pub(crate) fn registered_file_count(&self) -> u32 {
self.registered_files
}
pub(crate) fn registered_buffer_count(&self) -> u32 {
self.registered_buffers
}
pub(crate) fn reserve_registered_files(&mut self, count: u32) {
self.registered_files = self.registered_files.saturating_add(count);
}
pub(crate) fn reserve_registered_buffers(&mut self, count: u32) {
self.registered_buffers = self.registered_buffers.saturating_add(count);
}
#[cfg(test)]
pub(crate) fn set_next_user_data_for_test(&mut self, next: usize) {
self.next_user_data = next;
}
}
#[cfg(test)]
mod tests;