double_buffer/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3
4use core::ops::{Deref, DerefMut};
5use core::borrow::{Borrow, BorrowMut};
6use core::fmt::{Debug, Formatter, Pointer};
7
8/// Encapsulates a piece of state that can be modified and
9/// we want all outside code to see the edit as a single
10/// atomic change.
11///
12/// # Trait implementations
13///
14/// If trait use an immutable reference ([`AsRef<T>`], [`Deref`], [`Borrow<T>`]...) give access to the current value
15/// and mutable references ([`AsMut<T>`], [`DerefMut`], [`BorrowMut<T>`]...) give access to the next value.
16///
17/// # Swapping
18///
19/// There are three ways to swap:
20///
21/// 1. [`DoubleBuffer::swap()`] - when swapping, the next value will have the previous current value.
22/// 2. [`DoubleBuffer::swap_with_clone()`] - when swapping, the next value will keep same and will be cloned to the current value.
23/// 3. [`DoubleBuffer::swap_with_default()`] - like [`DoubleBuffer::swap()`] but the next value will be set to the default value of the type.
24///
25/// Note that for the third way, the type must implement [`Default`].
26///
27/// You can read about the two ways [how the buffers are swapped](https://gameprogrammingpatterns.com/double-buffer.html#how-are-the-buffers-swapped)
28/// in "Game Programming Patterns" by Robert Nystrom.
29///
30/// ## Swapping performance
31///
32/// If it's not important to keep the pointer address of the current value unchanged,
33/// [`DoubleBuffer::swap()`] is the best option.
34///
35/// Or [`DoubleBuffer::swap_with_default()`] if the type implements [`Default`] and
36/// starts with the default value is important.
37///
38/// Only use [`DoubleBuffer::swap_with_clone()`] if it's important to keep the pointer
39/// address of the current value unchanged.
40///
41/// # Examples
42///
43/// The following example shows how the buffer is swapped with the three ways:
44///
45/// ```
46/// # use double_buffer::DoubleBuffer;
47/// let mut buffer: DoubleBuffer<[u8; 32]> = DoubleBuffer::default();
48/// print!("{:?}", buffer); // DoubleBuffer { current: [0, ...], next: [0, ...] }
49///
50/// buffer[0] = 1;
51/// print!("{:?}", buffer); // DoubleBuffer { current: [0, ...], next: [1, ...] }
52///
53/// buffer.swap();
54/// print!("{:?}", buffer); // DoubleBuffer { current: [1, ...], next: [0, ...] }
55///
56/// buffer[0] = 2;
57/// print!("{:?}", buffer); // DoubleBuffer { current: [1, ...], next: [2, ...] }
58///
59/// buffer.swap_with_clone();
60/// print!("{:?}", buffer); // DoubleBuffer { current: [2, ...], next: [2, ...] }
61///
62/// buffer[0] = 3;
63/// print!("{:?}", buffer); // DoubleBuffer { current: [2, ...], next: [3, ...] }
64///
65/// buffer.swap_with_default();
66/// print!("{:?}", buffer); // DoubleBuffer { current: [3, ...], next: [0, ...] }
67/// ```
68pub struct DoubleBuffer<T> {
69    swapped: bool,
70    buffers: [T; 2],
71}
72
73impl<T> DoubleBuffer<T> {
74    #[inline]
75    pub const fn new(current: T, next: T) -> Self {
76        Self { swapped: false, buffers: [current, next] }
77    }
78
79    /// Swaps the current and next values,
80    /// then writes will be over the previous current value.
81    ///
82    /// This changes the pointer address of the current value.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// # use double_buffer::DoubleBuffer;
88    /// let mut buffer: DoubleBuffer<[u8; 8192]> = DoubleBuffer::new([0; 8192], [0; 8192]);
89    /// let first_address = format!("{:p}", buffer);
90    /// buffer.swap();
91    /// let second_address = format!("{:p}", buffer);
92    /// // The addresses are different.
93    /// assert_ne!(first_address, second_address);
94    /// ```
95    #[inline]
96    pub fn swap(&mut self) {
97        self.swapped = !self.swapped;
98    }
99
100    #[inline]
101    const fn current_offset(&self) -> usize {
102        if self.swapped {
103            return 1;
104        }
105        return 0;
106    }
107
108    #[inline]
109    const fn next_offset(&self) -> usize {
110        if self.swapped {
111            return 0;
112        }
113        return 1;
114    }
115
116    #[inline]
117    const fn current(&self) -> &T {
118        &self.buffers[self.current_offset()]
119    }
120
121    #[inline]
122    const fn next(&self) -> &T {
123        &self.buffers[self.next_offset()]
124    }
125
126    #[inline]
127    fn current_mut(&mut self) -> &mut T {
128        &mut self.buffers[self.current_offset()]
129    }
130
131    #[inline]
132    fn next_mut(&mut self) -> &mut T {
133        &mut self.buffers[self.next_offset()]
134    }
135}
136
137impl<T: Clone> DoubleBuffer<T> {
138    /// Clone the next value to the current value,
139    /// then writes will continue over the same next value.
140    ///
141    /// This let the pointer address of the current value unchanged.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// # use double_buffer::DoubleBuffer;
147    /// let mut buffer: DoubleBuffer<[u8; 8192]> = DoubleBuffer::new([0; 8192], [0; 8192]);
148    /// let first_address = format!("{:p}", buffer);
149    /// buffer.swap_with_clone();
150    /// let second_address = format!("{:p}", buffer);
151    /// // The addresses are different.
152    /// assert_eq!(first_address, second_address);
153    /// ```
154    #[inline]
155    pub fn swap_with_clone(&mut self) {
156        let next = self.next().clone();
157        let current = self.current_mut();
158        *current = next;
159    }
160}
161
162impl<T: Default> DoubleBuffer<T> {
163    /// Swaps buffers like [`DoubleBuffer::swap()`] and sets the next
164    /// value to the default value of the type, then writes will be
165    /// over the default value.
166    #[inline]
167    pub fn swap_with_default(&mut self) {
168        self.swap();
169        let next = self.next_mut();
170        *next = T::default();
171    }
172}
173
174impl<T: Debug> Debug for DoubleBuffer<T> {
175    #[inline]
176    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
177        f.debug_struct("DoubleBuffer")
178            .field("current", self.current())
179            .field("next", self.next())
180            .finish()
181    }
182}
183
184impl<T> Pointer for DoubleBuffer<T> {
185    #[inline]
186    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
187        write!(f, "{:p}", self.current())
188    }
189}
190
191impl<T: Default> Default for DoubleBuffer<T> {
192    #[inline]
193    fn default() -> Self {
194        Self::new(T::default(), T::default())
195    }
196}
197
198impl<T> Deref for DoubleBuffer<T> {
199    type Target = T;
200
201    #[inline]
202    fn deref(&self) -> &Self::Target {
203        self.current()
204    }
205}
206
207impl<T> DerefMut for DoubleBuffer<T> {
208    #[inline]
209    fn deref_mut(&mut self) -> &mut Self::Target {
210        self.next_mut()
211    }
212}
213
214impl<T> Borrow<T> for DoubleBuffer<T> {
215    #[inline]
216    fn borrow(&self) -> &T {
217        self.current()
218    }
219}
220
221impl<T> BorrowMut<T> for DoubleBuffer<T> {
222    #[inline]
223    fn borrow_mut(&mut self) -> &mut T {
224        self.next_mut()
225    }
226}
227
228impl<T> AsRef<T> for DoubleBuffer<T> {
229    #[inline]
230    fn as_ref(&self) -> &T {
231        self.current()
232    }
233}
234
235impl<T> AsMut<T> for DoubleBuffer<T> {
236    #[inline]
237    fn as_mut(&mut self) -> &mut T {
238        self.next_mut()
239    }
240}
241
242impl<T: PartialEq> PartialEq<T> for DoubleBuffer<T> {
243    #[inline]
244    fn eq(&self, other: &T) -> bool {
245        self.current().eq(other)
246    }
247}
248
249impl<T: PartialEq> PartialEq for DoubleBuffer<T> {
250    #[inline]
251    fn eq(&self, other: &Self) -> bool {
252        self.current().eq(other.current())
253    }
254}
255
256impl<T: Eq> Eq for DoubleBuffer<T> {}
257
258impl<T: PartialOrd> PartialOrd<T> for DoubleBuffer<T> {
259    #[inline]
260    fn partial_cmp(&self, other: &T) -> Option<core::cmp::Ordering> {
261        self.current().partial_cmp(other)
262    }
263}
264
265impl<T: PartialOrd> PartialOrd for DoubleBuffer<T> {
266    #[inline]
267    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
268        self.current().partial_cmp(other.current())
269    }
270}
271
272impl<T: Ord> Ord for DoubleBuffer<T> {
273    #[inline]
274    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
275        self.current().cmp(other.current())
276    }
277}
278
279#[cfg(test)]
280mod tests {
281    use super::*;
282
283    #[test]
284    fn test_access_and_modify_with_swap() {
285        let mut buffer: DoubleBuffer<u32> = DoubleBuffer::new(1, 2);
286        assert_eq!(buffer, 1);
287
288        *buffer = 3;
289        assert_eq!(buffer, 1);
290
291        buffer.swap();
292        assert_eq!(buffer, 3);
293    }
294
295    #[test]
296    fn test_access_and_modify_with_swap_with_clone() {
297        let mut buffer: DoubleBuffer<u32> = DoubleBuffer::new(1, 2);
298        assert_eq!(buffer, 1);
299
300        *buffer = 3;
301        assert_eq!(buffer, 1);
302
303        buffer.swap_with_clone();
304        assert_eq!(buffer, 3);
305    }
306
307    #[test]
308    fn test_access_and_modify_with_swap_with_default() {
309        let mut buffer: DoubleBuffer<u32> = DoubleBuffer::new(1, 2);
310        assert_eq!(buffer, 1);
311
312        *buffer = 3;
313        assert_eq!(buffer, 1);
314
315        buffer.swap_with_default();
316        assert_eq!(buffer, 3);
317    }
318
319    #[test]
320    fn test_swap() {
321        let mut buffer: DoubleBuffer<u32> = DoubleBuffer::new(1, 2);
322        assert_eq!(*buffer.current(), 1);
323        assert_eq!(*buffer.next(), 2);
324
325        buffer.swap();
326        assert_eq!(*buffer.current(), 2);
327        assert_eq!(*buffer.next(), 1);
328    }
329
330    #[test]
331    fn test_swap_with_clone() {
332        let mut buffer: DoubleBuffer<u32> = DoubleBuffer::new(1, 2);
333        assert_eq!(*buffer.current(), 1);
334        assert_eq!(*buffer.next(), 2);
335
336        buffer.swap_with_clone();
337        assert_eq!(*buffer.current(), 2);
338        assert_eq!(*buffer.next(), 2);
339    }
340
341    #[test]
342    fn test_swap_with_default() {
343        let mut buffer: DoubleBuffer<u32> = DoubleBuffer::new(1, 2);
344        assert_eq!(*buffer.current(), 1);
345        assert_eq!(*buffer.next(), 2);
346
347        buffer.swap_with_default();
348        assert_eq!(*buffer.current(), 2);
349        assert_eq!(*buffer.next(), 0);
350    }
351
352    #[test]
353    fn test_greater_and_less_than() {
354        let mut buffer: DoubleBuffer<i32> = DoubleBuffer::default();
355        *buffer = 1;
356        assert!(buffer > -1);
357        assert!(buffer < 1);
358
359        buffer.swap();
360        assert!(buffer > 0);
361        assert!(buffer < 2);
362    }
363
364    #[test]
365    fn test_modify_bytes_array() {
366        let mut buffer: DoubleBuffer<[u8; 3]> = DoubleBuffer::default();
367        buffer[1] = 2;
368        assert_eq!(buffer[1], 0);
369        assert_eq!(buffer, [0, 0, 0]);
370
371        assert_eq!(*buffer.current(), [0, 0, 0]);
372        assert_eq!(*buffer.next(), [0, 2, 0]);
373
374        buffer.swap();
375        assert_eq!(buffer[1], 2);
376        assert_eq!(buffer, [0, 2, 0]);
377
378        assert_eq!(*buffer.current(), [0, 2, 0]);
379        assert_eq!(*buffer.next(), [0, 0, 0]);
380    }
381
382    #[test]
383    fn test_for_iter_mut_bytes_array() {
384        let mut buffer: DoubleBuffer<[u8; 3]> = DoubleBuffer::default();
385        buffer[1] = 2;
386
387        assert_eq!(*buffer.current(), [0, 0, 0]);
388        assert_eq!(*buffer.next(), [0, 2, 0]);
389
390        for byte in buffer.iter_mut() {
391            *byte += 1;
392        }
393
394        assert_eq!(*buffer.current(), [0, 0, 0]);
395        assert_eq!(*buffer.next(), [1, 3, 1]);
396    }
397}