#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(super) struct CompletionQueueRing
{
head: NonNull<AtomicU32>,
tail: NonNull<AtomicU32>,
ring_mask: NonNull<u32>,
ring_entries: NonNull<u32>,
overflow: NonNull<AtomicU32>,
completion_queue_entries: NonNull<io_uring_cqe>,
}
impl CompletionQueueRing
{
#[inline(always)]
fn new(submission_queue_and_completion_queue: &MappedMemory, completion_queue_offsets: &io_cqring_offsets) -> Self
{
let memory = submission_queue_and_completion_queue.virtual_address();
Self
{
head: memory.aligned_pointer_to_value::<AtomicU32>(completion_queue_offsets.head as usize),
tail: memory.aligned_pointer_to_value::<AtomicU32>(completion_queue_offsets.head as usize),
ring_mask: memory.aligned_pointer_to_value::<u32>(completion_queue_offsets.head as usize),
ring_entries: memory.aligned_pointer_to_value::<u32>(completion_queue_offsets.head as usize),
overflow: memory.aligned_pointer_to_value::<AtomicU32>(completion_queue_offsets.head as usize),
completion_queue_entries: memory.aligned_pointer_to_value::<io_uring_cqe>(completion_queue_offsets.cqes as usize),
}
}
#[inline(always)]
pub(crate) fn overflow(&self) -> u32
{
self.overflow.load_acquire()
}
#[inline]
pub(crate) fn is_empty(&self) -> bool
{
self.length() == 0
}
#[inline]
pub(crate) fn is_full(&self) -> bool
{
self.length() == self.array_length()
}
#[inline(always)]
pub(crate) fn available(&self) -> u32
{
self.array_length() - self.length()
}
#[inline(always)]
pub(crate) fn length(&self) -> u32
{
let head = self.head.load_non_atomically();
let tail = self.tail.load_acquire();
tail.wrapping_sub(head)
}
#[inline(always)]
fn array_length(&self) -> u32
{
self.ring_entries.unsynchronized_value()
}
}