1use crate::utils::ring_buffer_ranges;
2use core::{mem::MaybeUninit, num::NonZeroUsize, ops::Range, ptr};
3
4/// Basic ring buffer functionality.
5///
6/// Provides an access to raw underlying memory and `head`/`tail` counters.
7///
8/// *It is recommended not to use this trait directly. Use [`Producer`](`crate::Producer`) and [`Consumer`](`crate::Consumer`) instead.*
9///
10/// # Details
11///
12/// The ring buffer consists of an array (of `capacity` size) and two counters: `head` and `tail`.
13/// When an item is extracted from the ring buffer it is taken from the `head` position and after that `head` is incremented.
14/// New item is appended to the `tail` position and `tail` is incremented after that.
15///
16/// The `head` and `tail` counters are modulo `2 * capacity` (not just `capacity`).
17/// It allows us to distinguish situations when the buffer is empty (`head == tail`) and when the buffer is full (`tail - head` modulo `2 * capacity` equals to `capacity`)
18/// without using the space for an extra element in container.
19/// And obviously we cannot store more than `capacity` items in the buffer, so `tail - head` modulo `2 * capacity` is not allowed to be greater than `capacity`.
20pub trait RbBase<T> {
21 /// Returns part of underlying raw ring buffer memory as slices.
22 ///
23 /// For more information see [`SharedStorage::as_mut_slices`](`crate::ring_buffer::storage::SharedStorage::as_mut_slices`).
24 ///
25 /// # Safety
26 ///
27 /// Only non-overlapping slices allowed to exist at the same time.
28 ///
29 /// Modifications of this data must properly update `head` and `tail` positions.
30 ///
31 /// *Accessing raw data is extremely unsafe.*
32 /// It is recommended to use [`Consumer::as_slices`](`crate::Consumer::as_slices`) and [`Producer::free_space_as_slices`](`crate::Producer::free_space_as_slices`) instead.
33 unsafe fn slices(
34 &self,
35 head: usize,
36 tail: usize,
37 ) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>]);
38
39 /// Capacity of the ring buffer.
40 ///
41 /// It is constant during the whole ring buffer lifetime.
42 fn capacity_nonzero(&self) -> NonZeroUsize;
43
44 /// Head position.
45 fn head(&self) -> usize;
46
47 /// Tail position.
48 fn tail(&self) -> usize;
49
50 /// Modulus for `head` and `tail` values.
51 ///
52 /// Equals to `2 * len`.
53 #[inline]
54 fn modulus(&self) -> NonZeroUsize {
55 unsafe { NonZeroUsize::new_unchecked(2 * self.capacity_nonzero().get()) }
56 }
57
58 /// The number of items stored in the buffer at the moment.
59 fn occupied_len(&self) -> usize {
60 let modulus = self.modulus();
61 (modulus.get() + self.tail() - self.head()) % modulus
62 }
63
64 /// The number of vacant places in the buffer at the moment.
65 fn vacant_len(&self) -> usize {
66 let modulus = self.modulus();
67 (self.capacity_nonzero().get() + self.head() - self.tail()) % modulus
68 }
69
70 /// Checks if the occupied range is empty.
71 fn is_empty(&self) -> bool {
72 self.head() == self.tail()
73 }
74
75 /// Checks if the vacant range is empty.
76 fn is_full(&self) -> bool {
77 self.vacant_len() == 0
78 }
79}
80
81/// Ring buffer read end.
82///
83/// Provides access to occupied memory and mechanism of item extraction.
84///
85/// *It is recommended not to use this trait directly. Use [`Producer`](`crate::Producer`) and [`Consumer`](`crate::Consumer`) instead.*
86pub trait RbRead<T>: RbBase<T> {
87 /// Sets the new **head** position.
88 ///
89 /// # Safety
90 ///
91 /// This call must cohere with ring buffer data modification.
92 ///
93 /// It is recommended to use `Self::advance_head` instead.
94 unsafe fn set_head(&self, value: usize);
95
96 /// Move **head** position by `count` items forward.
97 ///
98 /// # Safety
99 ///
100 /// First `count` items in occupied area must be **initialized** before this call.
101 ///
102 /// *In debug mode panics if `count` is greater than number of items in the ring buffer.*
103 unsafe fn advance_head(&self, count: usize) {
104 debug_assert!(count <= self.occupied_len());
105 self.set_head((self.head() + count) % self.modulus());
106 }
107
108 /// Returns a pair of ranges of [`Self::occupied_slices`] location in underlying container.
109 #[inline]
110 fn occupied_ranges(&self) -> (Range<usize>, Range<usize>) {
111 ring_buffer_ranges(self.capacity_nonzero(), self.head(), self.tail())
112 }
113
114 /// Provides a direct mutable access to the ring buffer occupied memory.
115 ///
116 /// Returns a pair of slices of stored items, the second one may be empty.
117 /// Elements with lower indices in slice are older. First slice contains older items that second one.
118 ///
119 /// # Safety
120 ///
121 /// All items are initialized. Elements must be removed starting from the beginning of first slice.
122 /// When all items are removed from the first slice then items must be removed from the beginning of the second slice.
123 ///
124 /// *This method must be followed by [`Self::advance_head`] call with the number of items being removed previously as argument.*
125 /// *No other mutating calls allowed before that.*
126 #[inline]
127 unsafe fn occupied_slices(&self) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>]) {
128 self.slices(self.head(), self.tail())
129 }
130
131 /// Removes items from the head of ring buffer and drops them.
132 ///
133 /// + If `count_or_all` is `Some(count)` then exactly `count` items will be removed.
134 /// *In debug mode panics if `count` is greater than number of items stored in the buffer.*
135 /// + If `count_or_all` is `None` then all items in ring buffer will be removed.
136 /// *If there is concurring producer activity then the buffer may be not empty after this call.*
137 ///
138 /// Returns the number of removed items.
139 ///
140 /// # Safety
141 ///
142 /// Must not be called concurrently.
143 unsafe fn skip_internal(&self, count_or_all: Option<usize>) -> usize {
144 let (left, right) = self.occupied_slices();
145 let count = match count_or_all {
146 Some(count) => {
147 debug_assert!(count <= left.len() + right.len());
148 count
149 }
150 None => left.len() + right.len(),
151 };
152 for elem in left.iter_mut().chain(right.iter_mut()).take(count) {
153 ptr::drop_in_place(elem.as_mut_ptr());
154 }
155 self.advance_head(count);
156 count
157 }
158}
159
160/// Ring buffer write end.
161///
162/// Provides access to vacant memory and mechanism of item insertion.
163///
164/// *It is recommended not to use this trait directly. Use [`Producer`](`crate::Producer`) and [`Consumer`](`crate::Consumer`) instead.*
165pub trait RbWrite<T>: RbBase<T> {
166 /// Sets the new **tail** position.
167 ///
168 /// # Safety
169 ///
170 /// This call must cohere with ring buffer data modification.
171 ///
172 /// It is recommended to use `Self::advance_tail` instead.
173 unsafe fn set_tail(&self, value: usize);
174
175 /// Move **tail** position by `count` items forward.
176 ///
177 /// # Safety
178 ///
179 /// First `count` items in vacant area must be **de-initialized** (dropped) before this call.
180 ///
181 /// *In debug mode panics if `count` is greater than number of vacant places in the ring buffer.*
182 unsafe fn advance_tail(&self, count: usize) {
183 debug_assert!(count <= self.vacant_len());
184 self.set_tail((self.tail() + count) % self.modulus());
185 }
186
187 /// Returns a pair of ranges of [`Self::vacant_slices`] location in underlying container.
188 #[inline]
189 fn vacant_ranges(&self) -> (Range<usize>, Range<usize>) {
190 ring_buffer_ranges(
191 self.capacity_nonzero(),
192 self.tail(),
193 self.head() + self.capacity_nonzero().get(),
194 )
195 }
196
197 /// Provides a direct access to the ring buffer vacant memory.
198 /// Returns a pair of slices of uninitialized memory, the second one may be empty.
199 ///
200 /// # Safety
201 ///
202 /// Vacant memory is uninitialized. Initialized items must be put starting from the beginning of first slice.
203 /// When first slice is fully filled then items must be put to the beginning of the second slice.
204 ///
205 /// *This method must be followed by [`Self::advance_tail`] call with the number of items being put previously as argument.*
206 /// *No other mutating calls allowed before that.*
207 #[inline]
208 unsafe fn vacant_slices(&self) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>]) {
209 self.slices(self.tail(), self.head() + self.capacity_nonzero().get())
210 }
211}
212