Skip to main content

ringbuf/traits/
observer.rs

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