Struct double_buffer::DoubleBuffer
source · pub struct DoubleBuffer<T> { /* private fields */ }Expand description
Encapsulates a piece of state that can be modified and we want all outside code to see the edit as a single atomic change.
Trait implementations
If trait use an immutable reference (AsRef<T>, Deref, Borrow<T>…) give access to the current value
and mutable references (AsMut<T>, DerefMut, BorrowMut<T>…) give access to the next value.
Swapping
There are three ways to swap:
DoubleBuffer::swap()- when swapping, the next value will have the previous current value.DoubleBuffer::swap_with_clone()- when swapping, the next value will keep same and will be cloned to the current value.DoubleBuffer::swap_with_default()- likeDoubleBuffer::swap()but the next value will be set to the default value of the type.
Note that for the third way, the type must implement Default.
You can read about the two ways how the buffers are swapped in “Game Programming Patterns” by Robert Nystrom.
Swapping Benchmarks
The following are the results in a i7 10th gen with 32GB RAM for a vec![u8; 8192] buffer:
DoubleBuffer::swap()- 1.6655 ns 1.6814 ns 1.6964 nsDoubleBuffer::swap_with_default()- 1.7783 ns 1.8009 ns 1.8262 nsDoubleBuffer::swap_with_clone()- 174.18 ns 177.86 ns 182.07 ns
If it’s not important to keep the pointer address of the current value unchanged,
DoubleBuffer::swap() is the best option, or DoubleBuffer::swap_with_default()
if the type implements Default and starts with the default value is important.
Only use DoubleBuffer::swap_with_clone() if it’s important to keep the pointer
address of the current value unchanged.
Examples
The following example shows how the buffer is swapped with the three ways:
let mut buffer: DoubleBuffer<[u8; 32]> = DoubleBuffer::default();
print!("{:?}", buffer); // DoubleBuffer { current: [0, ...], next: [0, ...] }
buffer[0] = 1;
print!("{:?}", buffer); // DoubleBuffer { current: [0, ...], next: [1, ...] }
buffer.swap();
print!("{:?}", buffer); // DoubleBuffer { current: [1, ...], next: [0, ...] }
buffer[0] = 2;
print!("{:?}", buffer); // DoubleBuffer { current: [1, ...], next: [2, ...] }
buffer.swap_with_clone();
print!("{:?}", buffer); // DoubleBuffer { current: [2, ...], next: [2, ...] }
buffer[0] = 3;
print!("{:?}", buffer); // DoubleBuffer { current: [2, ...], next: [3, ...] }
buffer.swap_with_default();
print!("{:?}", buffer); // DoubleBuffer { current: [3, ...], next: [0, ...] }Implementations§
source§impl<T> DoubleBuffer<T>
impl<T> DoubleBuffer<T>
pub const fn new(current: T, next: T) -> Self
sourcepub fn swap(&mut self)
pub fn swap(&mut self)
Swaps the current and next values, then writes will be over the previous current value.
This changes the pointer address of the current value.
Examples
let mut buffer: DoubleBuffer<[u8; 8192]> = DoubleBuffer::new([0; 8192], [0; 8192]);
let first_address = format!("{:p}", buffer);
buffer.swap();
let second_address = format!("{:p}", buffer);
// The addresses are different.
assert_ne!(first_address, second_address);source§impl<T: Clone> DoubleBuffer<T>
impl<T: Clone> DoubleBuffer<T>
sourcepub fn swap_with_clone(&mut self)
pub fn swap_with_clone(&mut self)
Clone the next value to the current value, then writes will continue over the same next value.
This let the pointer address of the current value unchanged.
Examples
let mut buffer: DoubleBuffer<[u8; 8192]> = DoubleBuffer::new([0; 8192], [0; 8192]);
let first_address = format!("{:p}", buffer);
buffer.swap_with_clone();
let second_address = format!("{:p}", buffer);
// The addresses are different.
assert_eq!(first_address, second_address);source§impl<T: Default> DoubleBuffer<T>
impl<T: Default> DoubleBuffer<T>
sourcepub fn swap_with_default(&mut self)
pub fn swap_with_default(&mut self)
Swaps buffers like DoubleBuffer::swap() and sets the next
value to the default value of the type, then writes will be
over the default value.
Trait Implementations§
source§impl<T> AsMut<T> for DoubleBuffer<T>
impl<T> AsMut<T> for DoubleBuffer<T>
source§impl<T> AsRef<T> for DoubleBuffer<T>
impl<T> AsRef<T> for DoubleBuffer<T>
source§impl<T> Borrow<T> for DoubleBuffer<T>
impl<T> Borrow<T> for DoubleBuffer<T>
source§impl<T> BorrowMut<T> for DoubleBuffer<T>
impl<T> BorrowMut<T> for DoubleBuffer<T>
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T: Debug> Debug for DoubleBuffer<T>
impl<T: Debug> Debug for DoubleBuffer<T>
source§impl<T: Default> Default for DoubleBuffer<T>
impl<T: Default> Default for DoubleBuffer<T>
source§impl<T> Deref for DoubleBuffer<T>
impl<T> Deref for DoubleBuffer<T>
source§impl<T> DerefMut for DoubleBuffer<T>
impl<T> DerefMut for DoubleBuffer<T>
source§impl<T: Ord> Ord for DoubleBuffer<T>
impl<T: Ord> Ord for DoubleBuffer<T>
source§impl<T: PartialEq> PartialEq<T> for DoubleBuffer<T>
impl<T: PartialEq> PartialEq<T> for DoubleBuffer<T>
source§impl<T: PartialEq> PartialEq for DoubleBuffer<T>
impl<T: PartialEq> PartialEq for DoubleBuffer<T>
source§impl<T: PartialOrd> PartialOrd<T> for DoubleBuffer<T>
impl<T: PartialOrd> PartialOrd<T> for DoubleBuffer<T>
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self and other) and is used by the <=
operator. Read moresource§impl<T: PartialOrd> PartialOrd for DoubleBuffer<T>
impl<T: PartialOrd> PartialOrd for DoubleBuffer<T>
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
self and other) and is used by the <=
operator. Read more