Skip to main content

ringbuf/traits/
observer.rs

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