ringbuf/traits/observer.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
use super::{utils::modulus, Based};
use core::{mem::MaybeUninit, num::NonZeroUsize};
/// Ring buffer observer.
///
/// Can observe ring buffer state but cannot safely access its data.
pub trait Observer {
type Item: Sized;
/// Capacity of the ring buffer.
///
/// It is constant during the whole ring buffer lifetime.
fn capacity(&self) -> NonZeroUsize;
/// Index of the last item in the ring buffer.
///
/// Index value is in range `0..(2 * capacity)`.
fn read_index(&self) -> usize;
/// Index of the next empty slot in the ring buffer.
///
/// Index value is in range `0..(2 * capacity)`.
fn write_index(&self) -> usize;
/// Get slice between `start` and `end` indices.
///
/// # Safety
///
/// Slice must not overlap with any mutable slice existing at the same time.
///
/// Non-`Sync` items must not be accessed from multiple threads at the same time.
unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]);
/// Get mutable slice between `start` and `end` indices.
///
/// # Safety
///
/// There must not exist overlapping slices at the same time.
unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]);
/// Whether read end is held by consumer.
fn read_is_held(&self) -> bool;
/// Whether write end is held by producer.
fn write_is_held(&self) -> bool;
/// The number of items stored in the buffer.
///
/// *Actual number may be greater or less than returned value due to concurring activity of producer or consumer respectively.*
fn occupied_len(&self) -> usize {
let modulus = modulus(self);
(modulus.get() + self.write_index() - self.read_index()) % modulus
}
/// The number of remaining free places in the buffer.
///
/// *Actual number may be greater or less than returned value due to concurring activity of consumer or producer respectively.*
fn vacant_len(&self) -> usize {
let modulus = modulus(self);
(self.capacity().get() + self.read_index() - self.write_index()) % modulus
}
/// Checks if the ring buffer is empty.
///
/// *The result may become irrelevant at any time because of concurring producer activity.*
#[inline]
fn is_empty(&self) -> bool {
self.read_index() == self.write_index()
}
/// Checks if the ring buffer is full.
///
/// *The result may become irrelevant at any time because of concurring consumer activity.*
#[inline]
fn is_full(&self) -> bool {
self.vacant_len() == 0
}
}
/// Trait used for delegating observer methods.
pub trait DelegateObserver: Based
where
Self::Base: Observer,
{
}
impl<D: DelegateObserver> Observer for D
where
D::Base: Observer,
{
type Item = <D::Base as Observer>::Item;
#[inline]
fn capacity(&self) -> NonZeroUsize {
self.base().capacity()
}
#[inline]
fn read_index(&self) -> usize {
self.base().read_index()
}
#[inline]
fn write_index(&self) -> usize {
self.base().write_index()
}
#[inline]
unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]) {
self.base().unsafe_slices(start, end)
}
#[inline]
unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]) {
self.base().unsafe_slices_mut(start, end)
}
#[inline]
fn read_is_held(&self) -> bool {
self.base().read_is_held()
}
#[inline]
fn write_is_held(&self) -> bool {
self.base().write_is_held()
}
#[inline]
fn occupied_len(&self) -> usize {
self.base().occupied_len()
}
#[inline]
fn vacant_len(&self) -> usize {
self.base().vacant_len()
}
#[inline]
fn is_empty(&self) -> bool {
self.base().is_empty()
}
#[inline]
fn is_full(&self) -> bool {
self.base().is_full()
}
}