sketchbook_wgpu/
double_buffer.rs

1use std::{sync::*, ops::*};
2
3#[derive(PartialEq, Eq, Debug)]
4enum Status {
5    Same,
6    Changed,
7}
8
9impl Default for Status {
10    fn default() -> Self {
11        Status::Same
12    }
13}
14
15pub struct DoubleBuffer<T> {
16    read_buffer: Arc<Mutex<(T, Status)>>,
17    write_buffer: T,
18}
19
20impl<T> DoubleBuffer<T> {
21    pub fn new() -> Self where T: Default {
22        Self {
23            read_buffer: Arc::default(),
24            write_buffer: T::default(),
25        }
26    }
27
28    pub fn split(self) -> (DoubleBufferRead<T>, DoubleBufferWrite<T>) {
29        (
30            DoubleBufferRead {
31                read_buffer: Arc::clone(&self.read_buffer),
32            },
33            DoubleBufferWrite {
34                read_buffer: self.read_buffer,
35                write_buffer: self.write_buffer,
36            }
37        )
38    }
39}
40
41pub struct DoubleBufferRead<T> {
42    read_buffer: Arc<Mutex<(T, Status)>>,
43}
44
45pub struct DoubleBufferReadGuard<'a, T> {
46    guard: MutexGuard<'a, (T, Status)>,
47}
48
49impl<'a, T> Deref for DoubleBufferReadGuard<'a, T> {
50    type Target = T;
51
52    fn deref(&self) -> &T {
53        &self.guard.0
54    }
55}
56
57impl<'a, T> DerefMut for DoubleBufferReadGuard<'a, T> {
58    fn deref_mut(&mut self) -> &mut T {
59        &mut self.guard.0
60    }
61}
62
63impl<T> DoubleBufferRead<T> {
64    pub fn if_changed(&self) -> Option<DoubleBufferReadGuard<T>> {
65        match self.read_buffer.lock() {
66            Ok(mut guard) => {
67                if guard.1 == Status::Changed {
68                    // mark buffer as same
69                    guard.1 = Status::Same;
70
71                    // return guard
72                    Some(DoubleBufferReadGuard { guard })
73                } else {
74                    None
75                }
76            },
77            Err(PoisonError { .. }) => None,
78        }
79    }
80}
81
82pub struct DoubleBufferWrite<T> {
83    read_buffer: Arc<Mutex<(T, Status)>>,
84    write_buffer: T,
85}
86
87impl<T> DoubleBufferWrite<T> {
88    pub fn swap(buffer: &mut Self) {
89        match buffer.read_buffer.lock() {
90            Ok(mut guard) => {
91                // mark buffer as changed
92                guard.1 = Status::Changed;
93
94                // swap the buffers
95                std::mem::swap(&mut guard.0, &mut buffer.write_buffer);
96            },
97            Err(PoisonError { .. }) => {},
98        }
99    }
100}
101
102impl<T> Deref for DoubleBufferWrite<T> {
103    type Target = T;
104
105    fn deref(&self) -> &T {
106        &self.write_buffer
107    }
108}
109
110impl<T> DerefMut for DoubleBufferWrite<T> {
111    fn deref_mut(&mut self) -> &mut T {
112        &mut self.write_buffer
113    }
114}