1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45#![deny(missing_docs)]
67//! A common handler for hanging_gets
89use thiserror::Error;
1011/// Function used to determine whether a change should cause any parked watchers to return.
12type ChangeFunction<T> = Box<dyn Fn(&T, &T) -> bool + Send + Sync + 'static>;
1314/// Trait that should be implemented to send data to the hanging get watcher.
15pub trait Sender<T> {
16/// Should send a response immediately to the sender.
17fn send_response(self, data: T);
18}
1920/// Default change function that checks for equality
21pub fn equality_change_function<T: PartialEq>() -> ChangeFunction<T> {
22 Box::new(|old: &T, new: &T| old != new)
23}
2425/// Handler for hanging gets.
26/// The common way to use this is to implement the Sender<T> trait for the FIDL responder that the handler is used for.
27/// There should be one instance of HangingGetHandler per interface per connection, as the handler needs to keep track
28/// of state per connection.
29pub struct WatchHandler<T, ST> {
30/// The callback to be parked in the handler.
31 /// There can only be one.
32watch_responder: Option<ST>,
33/// Represents the current state of the system.
34current_value: Option<T>,
35/// The last value that was sent to the client.
36last_sent_value: Option<T>,
37/// Function called on change. If function returns true, tells the handler that it should send to the hanging get.
38change_function: ChangeFunction<T>,
39}
4041impl<T, ST> WatchHandler<T, ST>
42where
43T: Clone + PartialEq + 'static,
44 ST: Sender<T> + 'static,
45{
46/// Creates a new instance of WatchHandler. If |initial_value| is provided, it will return
47 /// immediately on first watch. Otherwise, the first watch returns when the value is set for
48 /// the first time.
49 /// Uses default change function which just checks for any change.
50pub fn create(initial_value: Option<T>) -> Self {
51Self::create_with_change_fn(equality_change_function(), initial_value)
52 }
53}
5455impl<T, ST> WatchHandler<T, ST>
56where
57T: Clone + 'static,
58 ST: Sender<T> + 'static,
59{
60/// Creates a new instance of WatchHandler. If |initial_value| is provided, it will return
61 /// immediately on first watch. Otherwise, the first watch returns when the value is set for
62 /// the first time.
63pub fn create_with_change_fn(
64 change_function: ChangeFunction<T>,
65 initial_value: Option<T>,
66 ) -> Self {
67Self {
68 watch_responder: None,
69 last_sent_value: None,
70 current_value: initial_value,
71 change_function: change_function,
72 }
73 }
7475/// Park a new hanging get in the handler. If a hanging get is already parked, returns the
76 /// new responder.
77pub fn watch(&mut self, responder: ST) -> Result<(), WatchError<ST>> {
78if let None = self.watch_responder {
79self.watch_responder = Some(responder);
80self.send_if_needed();
81Ok(())
82 } else {
83Err(WatchError { responder })
84 }
85 }
8687/// Sets a new change function.
88 /// The hanging get will only return when the change function evaluates to true when comparing the last value sent to
89 /// the client and the current value. Takes effect immediately; if change function evaluates to true then the pending
90 /// responder will be called.
91pub fn set_change_function(&mut self, change_function: ChangeFunction<T>) {
92self.change_function = change_function;
93self.send_if_needed();
94 }
9596/// Called to update the current value of the handler, sending changes using the watcher if needed.
97pub fn set_value(&mut self, new_value: T) {
98self.current_value = Some(new_value);
99self.send_if_needed();
100 }
101102/// Called when receiving a notification that value has changed.
103fn send_if_needed(&mut self) {
104let value_to_send = match (self.last_sent_value.as_ref(), self.current_value.as_ref()) {
105 (Some(last), Some(current)) if (self.change_function)(last, current) => Some(current),
106 (Some(_), Some(_)) => None,
107 (None, Some(current)) => Some(current),
108 (_, None) => None,
109 };
110111if let Some(value) = value_to_send {
112if let Some(responder) = self.watch_responder.take() {
113 responder.send_response(value.clone());
114self.last_sent_value = Some(value.clone());
115 }
116 }
117 }
118}
119120/// Error returned if watch fails.
121#[derive(Error)]
122#[error("Inconsistent state; existing handler in state")]
123pub struct WatchError<ST> {
124/// The responder that could not be parked.
125pub responder: ST,
126}
127128impl<ST> std::fmt::Debug for WatchError<ST> {
129fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
130write!(f, "{}", self)
131 }
132}
133134#[cfg(test)]
135mod tests {
136use super::*;
137use std::cell::RefCell;
138use std::rc::Rc;
139140const ID_INVALID: i32 = 0;
141const ID1: i32 = 1;
142const ID2: i32 = 2;
143const ID3: i32 = 3;
144const ID4: i32 = 4;
145146#[derive(Clone, PartialEq)]
147struct TestStruct {
148 id: i32,
149 }
150151#[derive(Debug, PartialEq)]
152struct TestSender {
153 sent_value: Rc<RefCell<i32>>,
154 }
155156impl Sender<TestStruct> for TestSender {
157fn send_response(self, data: TestStruct) {
158self.sent_value.replace(data.id);
159 }
160 }
161162#[test]
163fn test_watch() {
164let mut handler =
165 WatchHandler::<TestStruct, TestSender>::create(Some(TestStruct { id: ID1 }));
166167let sent_value = Rc::new(RefCell::new(ID_INVALID));
168 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
169170// First call should return immediately
171assert_eq!((*sent_value.borrow()), ID1);
172173let sent_value = Rc::new(RefCell::new(ID_INVALID));
174 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
175176// Second call doesn't return because value hasn't changed
177assert_eq!((*sent_value.borrow()), ID_INVALID);
178179 handler.set_value(TestStruct { id: ID2 });
180181// When value changes, returns immediately
182assert_eq!((*sent_value.borrow()), ID2);
183184 handler.set_value(TestStruct { id: ID3 });
185186let sent_value = Rc::new(RefCell::new(ID_INVALID));
187 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
188189// Call after change also returns immediately
190assert_eq!((*sent_value.borrow()), ID3);
191 }
192193#[test]
194fn test_watch_no_initial() {
195let mut handler = WatchHandler::<TestStruct, TestSender>::create(None);
196197let sent_value = Rc::new(RefCell::new(ID_INVALID));
198 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
199200// First call does not return until value is set
201assert_eq!((*sent_value.borrow()), ID_INVALID);
202203 handler.set_value(TestStruct { id: ID1 });
204assert_eq!((*sent_value.borrow()), ID1);
205206let mut handler = WatchHandler::<TestStruct, TestSender>::create(None);
207 handler.set_value(TestStruct { id: ID2 });
208209let sent_value = Rc::new(RefCell::new(ID_INVALID));
210 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
211212// First call returns immediately if value is already set.
213assert_eq!((*sent_value.borrow()), ID2);
214 }
215216#[test]
217fn test_watch_fails() {
218let mut handler =
219 WatchHandler::<TestStruct, TestSender>::create(Some(TestStruct { id: ID1 }));
220221let sent_value = Rc::new(RefCell::new(ID_INVALID));
222// first watch returns immediately
223handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
224225let sent_value = Rc::new(RefCell::new(ID_INVALID));
226// second watch hangs
227handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
228229let sent_value = Rc::new(RefCell::new(ID4));
230// third results in an error
231let result = handler.watch(TestSender { sent_value: sent_value.clone() });
232233assert_eq!(result.unwrap_err().responder, TestSender { sent_value: sent_value.clone() });
234 }
235236#[test]
237fn test_watch_with_change_function() {
238let mut handler = WatchHandler::<TestStruct, TestSender>::create_with_change_fn(
239 equality_change_function(),
240Some(TestStruct { id: ID1 }),
241 );
242let sent_value = Rc::new(RefCell::new(ID_INVALID));
243244 handler.set_change_function(Box::new(|_old, _new| false));
245 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
246247// first watch should return immediately regardless
248assert_eq!((*sent_value.borrow()), ID1);
249250let sent_value = Rc::new(RefCell::new(ID_INVALID));
251 handler.set_change_function(Box::new(|old, new| new.id - old.id > 1));
252 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
253 handler.set_value(TestStruct { id: ID2 });
254255// If change function returns false, will not return
256assert_eq!((*sent_value.borrow()), ID_INVALID);
257258 handler.set_value(TestStruct { id: ID3 });
259260// But subsequent change that satsifies change function will cause return
261assert_eq!((*sent_value.borrow()), ID3);
262263// Setting the change function with a pending watch should cause sender to send.
264let sent_value = Rc::new(RefCell::new(ID_INVALID));
265 handler.set_change_function(Box::new(|_old, _new| false));
266 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
267 handler.set_value(TestStruct { id: ID4 });
268269assert_eq!((*sent_value.borrow()), ID_INVALID);
270271 handler.set_change_function(Box::new(|_old, _new| true));
272assert_eq!((*sent_value.borrow()), ID4);
273 }
274275#[test]
276fn test_watch_with_change_fn_no_initial() {
277let mut handler = WatchHandler::<TestStruct, TestSender>::create_with_change_fn(
278 Box::new(|_old, _new| false),
279None,
280 );
281282let sent_value = Rc::new(RefCell::new(ID_INVALID));
283 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
284285// First call does not return until value is set
286assert_eq!((*sent_value.borrow()), ID_INVALID);
287288// First value returns after set regardless of change fn
289handler.set_value(TestStruct { id: ID1 });
290assert_eq!((*sent_value.borrow()), ID1);
291292let mut handler = WatchHandler::<TestStruct, TestSender>::create_with_change_fn(
293 Box::new(|_old, _new| false),
294None,
295 );
296 handler.set_value(TestStruct { id: ID2 });
297298let sent_value = Rc::new(RefCell::new(ID_INVALID));
299 handler.watch(TestSender { sent_value: sent_value.clone() }).unwrap();
300301// First call returns immediately if value is already set regardless of change fn
302assert_eq!((*sent_value.borrow()), ID2);
303 }
304}