aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync/src
diff options
context:
space:
mode:
authorPeter Krull <[email protected]>2024-09-23 20:29:50 +0200
committerPeter Krull <[email protected]>2024-09-23 20:29:50 +0200
commit999807f226623669a9cfc8ca218d3c81f0c04a77 (patch)
tree42d9e30722e2528d5f0eaf0144ea4f64b8a5462c /embassy-sync/src
parenta669611d7c8fb17666f35086ea20c476b6029854 (diff)
Added SealedWatchBehavior to limit access to core functions
Diffstat (limited to 'embassy-sync/src')
-rw-r--r--embassy-sync/src/watch.rs137
1 files changed, 71 insertions, 66 deletions
diff --git a/embassy-sync/src/watch.rs b/embassy-sync/src/watch.rs
index 1b4a8b589..4b7ffa5fc 100644
--- a/embassy-sync/src/watch.rs
+++ b/embassy-sync/src/watch.rs
@@ -76,28 +76,14 @@ struct WatchState<const N: usize, T: Clone> {
76 receiver_count: usize, 76 receiver_count: usize,
77} 77}
78 78
79/// A trait representing the 'inner' behavior of the `Watch`. 79trait SealedWatchBehavior<T> {
80pub trait WatchBehavior<T: Clone> {
81 /// Sends a new value to the `Watch`.
82 fn send(&self, val: T);
83
84 /// Clears the value of the `Watch`.
85 fn clear(&self);
86
87 /// Poll the `Watch` for the current value, making it as seen. 80 /// Poll the `Watch` for the current value, making it as seen.
88 fn poll_get(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T>; 81 fn poll_get(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T>;
89 82
90 /// Tries to get the value of the `Watch`, marking it as seen, if an id is given.
91 fn try_get(&self, id: Option<&mut u64>) -> Option<T>;
92
93 /// Poll the `Watch` for the value if it matches the predicate function 83 /// Poll the `Watch` for the value if it matches the predicate function
94 /// `f`, making it as seen. 84 /// `f`, making it as seen.
95 fn poll_get_and(&self, id: &mut u64, f: &mut dyn Fn(&T) -> bool, cx: &mut Context<'_>) -> Poll<T>; 85 fn poll_get_and(&self, id: &mut u64, f: &mut dyn Fn(&T) -> bool, cx: &mut Context<'_>) -> Poll<T>;
96 86
97 /// Tries to get the value of the `Watch` if it matches the predicate function
98 /// `f`, marking it as seen.
99 fn try_get_and(&self, id: Option<&mut u64>, f: &mut dyn Fn(&T) -> bool) -> Option<T>;
100
101 /// Poll the `Watch` for a changed value, marking it as seen, if an id is given. 87 /// Poll the `Watch` for a changed value, marking it as seen, if an id is given.
102 fn poll_changed(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T>; 88 fn poll_changed(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T>;
103 89
@@ -112,8 +98,16 @@ pub trait WatchBehavior<T: Clone> {
112 /// predicate function `f`, marking it as seen. 98 /// predicate function `f`, marking it as seen.
113 fn try_changed_and(&self, id: &mut u64, f: &mut dyn Fn(&T) -> bool) -> Option<T>; 99 fn try_changed_and(&self, id: &mut u64, f: &mut dyn Fn(&T) -> bool) -> Option<T>;
114 100
115 /// Checks if the `Watch` is been initialized with a value. 101 /// Used when a receiver is dropped to decrement the receiver count.
116 fn contains_value(&self) -> bool; 102 ///
103 /// ## This method should not be called by the user.
104 fn drop_receiver(&self);
105
106 /// Clears the value of the `Watch`.
107 fn clear(&self);
108
109 /// Sends a new value to the `Watch`.
110 fn send(&self, val: T);
117 111
118 /// Modify the value of the `Watch` using a closure. Returns `false` if the 112 /// Modify the value of the `Watch` using a closure. Returns `false` if the
119 /// `Watch` does not already contain a value. 113 /// `Watch` does not already contain a value.
@@ -122,30 +116,23 @@ pub trait WatchBehavior<T: Clone> {
122 /// Modify the value of the `Watch` using a closure. Returns `false` if the 116 /// Modify the value of the `Watch` using a closure. Returns `false` if the
123 /// `Watch` does not already contain a value. 117 /// `Watch` does not already contain a value.
124 fn send_if_modified(&self, f: &mut dyn Fn(&mut Option<T>) -> bool); 118 fn send_if_modified(&self, f: &mut dyn Fn(&mut Option<T>) -> bool);
125
126 /// Used when a receiver is dropped to decrement the receiver count.
127 ///
128 /// ## This method should not be called by the user.
129 fn drop_receiver(&self);
130} 119}
131 120
132impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N> { 121/// A trait representing the 'inner' behavior of the `Watch`.
133 fn send(&self, val: T) { 122#[allow(private_bounds)]
134 self.mutex.lock(|state| { 123pub trait WatchBehavior<T: Clone>: SealedWatchBehavior<T> {
135 let mut s = state.borrow_mut(); 124 /// Tries to get the value of the `Watch`, marking it as seen, if an id is given.
136 s.data = Some(val); 125 fn try_get(&self, id: Option<&mut u64>) -> Option<T>;
137 s.current_id += 1;
138 s.wakers.wake();
139 })
140 }
141 126
142 fn clear(&self) { 127 /// Tries to get the value of the `Watch` if it matches the predicate function
143 self.mutex.lock(|state| { 128 /// `f`, marking it as seen.
144 let mut s = state.borrow_mut(); 129 fn try_get_and(&self, id: Option<&mut u64>, f: &mut dyn Fn(&T) -> bool) -> Option<T>;
145 s.data = None; 130
146 }) 131 /// Checks if the `Watch` is been initialized with a value.
147 } 132 fn contains_value(&self) -> bool;
133}
148 134
135impl<M: RawMutex, T: Clone, const N: usize> SealedWatchBehavior<T> for Watch<M, T, N> {
149 fn poll_get(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T> { 136 fn poll_get(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T> {
150 self.mutex.lock(|state| { 137 self.mutex.lock(|state| {
151 let mut s = state.borrow_mut(); 138 let mut s = state.borrow_mut();
@@ -162,16 +149,6 @@ impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N>
162 }) 149 })
163 } 150 }
164 151
165 fn try_get(&self, id: Option<&mut u64>) -> Option<T> {
166 self.mutex.lock(|state| {
167 let s = state.borrow();
168 if let Some(id) = id {
169 *id = s.current_id;
170 }
171 s.data.clone()
172 })
173 }
174
175 fn poll_get_and(&self, id: &mut u64, f: &mut dyn Fn(&T) -> bool, cx: &mut Context<'_>) -> Poll<T> { 152 fn poll_get_and(&self, id: &mut u64, f: &mut dyn Fn(&T) -> bool, cx: &mut Context<'_>) -> Poll<T> {
176 self.mutex.lock(|state| { 153 self.mutex.lock(|state| {
177 let mut s = state.borrow_mut(); 154 let mut s = state.borrow_mut();
@@ -188,21 +165,6 @@ impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N>
188 }) 165 })
189 } 166 }
190 167
191 fn try_get_and(&self, id: Option<&mut u64>, f: &mut dyn Fn(&T) -> bool) -> Option<T> {
192 self.mutex.lock(|state| {
193 let s = state.borrow();
194 match s.data {
195 Some(ref data) if f(data) => {
196 if let Some(id) = id {
197 *id = s.current_id;
198 }
199 Some(data.clone())
200 }
201 _ => None,
202 }
203 })
204 }
205
206 fn poll_changed(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T> { 168 fn poll_changed(&self, id: &mut u64, cx: &mut Context<'_>) -> Poll<T> {
207 self.mutex.lock(|state| { 169 self.mutex.lock(|state| {
208 let mut s = state.borrow_mut(); 170 let mut s = state.borrow_mut();
@@ -261,10 +223,6 @@ impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N>
261 }) 223 })
262 } 224 }
263 225
264 fn contains_value(&self) -> bool {
265 self.mutex.lock(|state| state.borrow().data.is_some())
266 }
267
268 fn drop_receiver(&self) { 226 fn drop_receiver(&self) {
269 self.mutex.lock(|state| { 227 self.mutex.lock(|state| {
270 let mut s = state.borrow_mut(); 228 let mut s = state.borrow_mut();
@@ -272,6 +230,22 @@ impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N>
272 }) 230 })
273 } 231 }
274 232
233 fn clear(&self) {
234 self.mutex.lock(|state| {
235 let mut s = state.borrow_mut();
236 s.data = None;
237 })
238 }
239
240 fn send(&self, val: T) {
241 self.mutex.lock(|state| {
242 let mut s = state.borrow_mut();
243 s.data = Some(val);
244 s.current_id += 1;
245 s.wakers.wake();
246 })
247 }
248
275 fn send_modify(&self, f: &mut dyn Fn(&mut Option<T>)) { 249 fn send_modify(&self, f: &mut dyn Fn(&mut Option<T>)) {
276 self.mutex.lock(|state| { 250 self.mutex.lock(|state| {
277 let mut s = state.borrow_mut(); 251 let mut s = state.borrow_mut();
@@ -292,6 +266,37 @@ impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N>
292 } 266 }
293} 267}
294 268
269impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N> {
270 fn try_get(&self, id: Option<&mut u64>) -> Option<T> {
271 self.mutex.lock(|state| {
272 let s = state.borrow();
273 if let Some(id) = id {
274 *id = s.current_id;
275 }
276 s.data.clone()
277 })
278 }
279
280 fn try_get_and(&self, id: Option<&mut u64>, f: &mut dyn Fn(&T) -> bool) -> Option<T> {
281 self.mutex.lock(|state| {
282 let s = state.borrow();
283 match s.data {
284 Some(ref data) if f(data) => {
285 if let Some(id) = id {
286 *id = s.current_id;
287 }
288 Some(data.clone())
289 }
290 _ => None,
291 }
292 })
293 }
294
295 fn contains_value(&self) -> bool {
296 self.mutex.lock(|state| state.borrow().data.is_some())
297 }
298}
299
295impl<M: RawMutex, T: Clone, const N: usize> Watch<M, T, N> { 300impl<M: RawMutex, T: Clone, const N: usize> Watch<M, T, N> {
296 /// Create a new `Watch` channel. 301 /// Create a new `Watch` channel.
297 pub const fn new() -> Self { 302 pub const fn new() -> Self {