firewheel_core/diff/
notify.rs1use crate::{
2 diff::{Diff, Patch},
3 event::ParamData,
4};
5use bevy_platform::sync::atomic::{AtomicU64, Ordering};
6
7#[inline(always)]
11fn increment_counter() -> u64 {
12 static NOTIFY_COUNTER: AtomicU64 = AtomicU64::new(1);
13
14 NOTIFY_COUNTER
15 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |current_val| {
16 current_val
17 .checked_add(1)
19 .or(Some(1))
21 })
22 .unwrap()
24}
25
26#[derive(Debug, Clone)]
37pub struct Notify<T> {
38 value: T,
39 counter: u64,
40}
41
42impl<T> Notify<T> {
43 pub fn new(value: T) -> Self {
59 Self {
60 value,
61 counter: increment_counter(),
62 }
63 }
64
65 #[inline(always)]
74 pub fn id(&self) -> u64 {
75 self.counter
76 }
77
78 pub fn as_mut_unsync(&mut self) -> &mut T {
80 &mut self.value
81 }
82
83 pub fn notify(&mut self) {
85 self.counter = increment_counter();
86 }
87}
88
89impl<T> AsRef<T> for Notify<T> {
90 fn as_ref(&self) -> &T {
91 &self.value
92 }
93}
94
95impl<T> AsMut<T> for Notify<T> {
96 fn as_mut(&mut self) -> &mut T {
97 self.counter = increment_counter();
98
99 &mut self.value
100 }
101}
102
103impl<T: Default> Default for Notify<T> {
104 fn default() -> Self {
105 Self::new(T::default())
106 }
107}
108
109impl<T> core::ops::Deref for Notify<T> {
110 type Target = T;
111
112 fn deref(&self) -> &Self::Target {
113 &self.value
114 }
115}
116
117impl<T> core::ops::DerefMut for Notify<T> {
118 fn deref_mut(&mut self) -> &mut Self::Target {
119 self.counter = increment_counter();
120
121 &mut self.value
122 }
123}
124
125impl<T: Clone + Send + Sync + 'static> Diff for Notify<T> {
126 fn diff<E: super::EventQueue>(
127 &self,
128 baseline: &Self,
129 path: super::PathBuilder,
130 event_queue: &mut E,
131 ) {
132 if self.counter != baseline.counter {
133 event_queue.push_param(ParamData::any(self.clone()), path);
134 }
135 }
136}
137
138impl<T: Clone + Send + Sync + 'static> Patch for Notify<T> {
139 type Patch = Self;
140
141 fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, super::PatchError> {
142 data.downcast_ref()
143 .ok_or(super::PatchError::InvalidData)
144 .cloned()
145 }
146
147 fn apply(&mut self, patch: Self::Patch) {
148 *self = patch;
149 }
150}
151
152#[cfg(test)]
153mod test {
154 use crate::diff::PathBuilder;
155
156 use super::*;
157
158 #[test]
159 fn test_identical_write() {
160 let baseline = Notify::new(0.5f32);
161 let mut value = baseline.clone();
162
163 let mut events = Vec::new();
164 value.diff(&baseline, PathBuilder::default(), &mut events);
165 assert_eq!(events.len(), 0);
166
167 *value = 0.5f32;
168
169 value.diff(&baseline, PathBuilder::default(), &mut events);
170 assert_eq!(events.len(), 1);
171 }
172}