Skip to main content

async_utils/hanging_get/
server.rs

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.
4
5use crate::hanging_get::error::HangingGetServerError;
6use core::hash::Hash;
7use fuchsia_sync::Mutex;
8use std::collections::HashMap;
9use std::sync::Arc;
10
11/// A broker of updates to some state, using the hanging get pattern.
12///
13/// The broker stores a state, and mediates state changes between
14/// [Publisher]s and [Subscriber]s.  Any [Publisher] can change the state at any
15/// time.  When the state is changed, all [Subscriber]s are notified with the new
16/// state.
17///
18/// To follow the hanging get pattern, when a [Subscriber] is first created,
19/// the current state is sent immediately.  Subsequent updates to the same
20/// subscriber are only sent when the state is modified.
21///
22/// * Use [HangingGet::new] to create a new broker for a single state item.
23/// * Use [HangingGet::new_publisher] to create an object that allows you to
24///   update the state.
25/// * Use [HangingGet::new_subscriber] to create an object that monitors for
26///   updates to the state.
27///
28/// ## Type parameters
29///
30/// * `S`: the type of the stored hanging get state.  This is the state that gets
31///   communicated to subscribers.
32/// * `O`: The type of the object used to notify of state change.
33/// * `F`: The type of a function used to send the new state content to an instance
34///   of `O`.  `F` gets passed the content of the new state, the object that it
35///   needs to notify, and is expected to return `true` if the notification was
36///   a success; otherwise it must return `false`.
37pub struct HangingGet<S, O, F: Fn(&S, O) -> bool> {
38    inner: Arc<Mutex<HangingGetInner<S, subscriber_key::Key, O, F>>>,
39    /// A [subscriber_key::Key] held by the broker to track the next unique key that the broker can
40    /// assign to a [Subscriber].
41    subscriber_key_generator: subscriber_key::Generator,
42}
43
44impl<S, O, F> HangingGet<S, O, F>
45where
46    F: Fn(&S, O) -> bool,
47{
48    /// Create a new broker.
49    ///
50    /// ## Args:
51    ///
52    /// * `state` is the initial state of the [HangingGet].
53    /// * `notify` is a function to notify observers of state of the state change.
54    pub fn new(state: S, notify: F) -> Self {
55        Self {
56            inner: Arc::new(Mutex::new(HangingGetInner::new(Some(state), notify))),
57            subscriber_key_generator: subscriber_key::Generator::default(),
58        }
59    }
60
61    /// Create a new broker, but delays any subscribers from being notified until the value is
62    /// initialized.
63    ///
64    /// ## Args:
65    ///
66    /// * `notify` is a function to notify observers of state of the state change.
67    ///
68    /// # Disclaimer:
69    /// This initialier is more prone to cause hangs if code is not properly setup. This
70    /// should only be used for patterns where the is no useful default state.
71    pub fn new_unknown_state(notify: F) -> Self {
72        Self {
73            inner: Arc::new(Mutex::new(HangingGetInner::new(None, notify))),
74            subscriber_key_generator: subscriber_key::Generator::default(),
75        }
76    }
77
78    /// Create a new [Publisher] that can make atomic updates to the state value.
79    pub fn new_publisher(&self) -> Publisher<S, O, F> {
80        Publisher { inner: self.inner.clone() }
81    }
82
83    /// Create a new [Subscriber] that represents a single hanging get client.
84    ///
85    /// The newly-created subscriber will be notified with the current state
86    /// immediately.  After the first notification, the subscriber will be
87    /// notified only if the state changes.
88    pub fn new_subscriber(&mut self) -> Subscriber<S, O, F> {
89        Subscriber { inner: self.inner.clone(), key: self.subscriber_key_generator.next().unwrap() }
90    }
91}
92
93/// A `Subscriber` can be used to register observation requests with the `HangingGet`.
94/// These will be notified when the state changes or immediately the first time
95/// a `Subscriber` registers an observation.
96///
97/// ## Type parameters
98///
99/// See [HangingGet] for the explanation of the type parameters `S`, `O`, `F`.
100pub struct Subscriber<S, O, F: Fn(&S, O) -> bool> {
101    inner: Arc<Mutex<HangingGetInner<S, subscriber_key::Key, O, F>>>,
102    key: subscriber_key::Key,
103}
104
105impl<S, O, F> Subscriber<S, O, F>
106where
107    F: Fn(&S, O) -> bool,
108{
109    /// Register a new observation.
110    ///
111    /// Errors occur when:
112    /// * A Subscriber attempts to register an observation when there is already an outstanding
113    ///   observation waiting on updates.
114    ///
115    /// Returns `observation` on error.
116    pub fn register(&self, observation: O) -> Result<(), HangingGetServerError> {
117        self.register2(observation).map_err(|_| HangingGetServerError::MultipleObservers)
118    }
119    /// Register a new observation.
120    ///
121    /// Errors occur when:
122    /// * A Subscriber attempts to register an observation when there is already an outstanding
123    ///   observation waiting on updates.
124    ///
125    /// Returns `observation` on error.
126    pub fn register2(&self, observation: O) -> Result<(), O> {
127        self.inner.lock().subscribe(self.key, observation)
128    }
129}
130
131impl<S, O, F> Drop for Subscriber<S, O, F>
132where
133    F: Fn(&S, O) -> bool,
134{
135    fn drop(&mut self) {
136        self.inner.lock().unsubscribe(self.key);
137    }
138}
139
140/// A `Publisher` is used to make changes to the state contained within a `HangingGet`.
141/// It is designed to be cheaply cloned and `Send`.
142///
143/// ## Type parameters
144///
145/// See [HangingGet] for the explanation of the generic types `S`, `O`, `F`.
146pub struct Publisher<S, O, F: Fn(&S, O) -> bool> {
147    inner: Arc<Mutex<HangingGetInner<S, subscriber_key::Key, O, F>>>,
148}
149
150impl<S, O, F: Fn(&S, O) -> bool> Clone for Publisher<S, O, F> {
151    /// Clones this [Publisher].
152    ///
153    /// It is cheap to clone a [Publisher].
154    fn clone(&self) -> Self {
155        Self { inner: self.inner.clone() }
156    }
157}
158
159impl<S, O, F> Publisher<S, O, F>
160where
161    F: Fn(&S, O) -> bool,
162{
163    /// Set the stored state to `S`. Subscribers will be updated.
164    pub fn set(&self, state: S) {
165        self.inner.lock().set(state)
166    }
167
168    /// Pass a function to the hanging get that can update the hanging get state in place.
169    ///
170    /// Any subscriber that has registered an observer will immediately be notified of the
171    /// update.
172    ///
173    /// ## Type parameters
174    ///
175    /// * `UpdateFn`: an update function: gets passed the new state, and returns `true`
176    ///   if the state has been updated with success.
177    pub fn update<UpdateFn>(&self, update: UpdateFn)
178    where
179        UpdateFn: FnOnce(&mut Option<S>) -> bool,
180    {
181        self.inner.lock().update(update)
182    }
183}
184
185/// A [HangingGetInner] object manages some internal state `S` and notifies observers of type `O`
186/// when their view of the state is outdated.
187///
188/// While it _can_ be used directly, most API consumers will want to use the higher level
189/// [HangingGet] object. `HangingGet` and its companion types provide `Send`
190/// for use from multiple threads or async tasks.
191///
192/// ## Type parameters
193///
194/// * `K` - the Key by which Observers are identified.
195/// * For other type args see [HangingGet].
196pub struct HangingGetInner<S, K, O, F: Fn(&S, O) -> bool> {
197    state: Option<S>,
198    notify: F,
199    observers: HashMap<K, Window<O>>,
200}
201
202impl<S, K, O, F> HangingGetInner<S, K, O, F>
203where
204    K: Eq + Hash,
205    F: Fn(&S, O) -> bool,
206{
207    fn notify_all(&mut self) {
208        for window in self.observers.values_mut() {
209            window.notify(&self.notify, self.state.as_ref().unwrap());
210        }
211    }
212
213    /// Create a new `HangingGetInner`.
214    /// `state` is the initial state of the HangingGetInner
215    /// `notify` is a `Fn` that is used to notify observers of state.
216    pub fn new(state: Option<S>, notify: F) -> Self {
217        Self { state, notify, observers: HashMap::new() }
218    }
219
220    /// Set the internal state value to `state` and notify all observers.
221    /// Note that notification is not conditional on the _value_ set by calling the `set` function.
222    /// Notification will occur regardless of whether the `state` value differs from the value
223    /// currently stored by `HangingGetInner`.
224    pub fn set(&mut self, state: S) {
225        self.state = Some(state);
226        self.notify_all();
227    }
228
229    /// Modify the internal state in-place using the `state_update` function. Notify all
230    /// observers if `state_update` returns true.
231    pub fn update(&mut self, state_update: impl FnOnce(&mut Option<S>) -> bool) {
232        if state_update(&mut self.state) {
233            self.notify_all();
234        }
235    }
236
237    /// Register an observer as a subscriber of the state.
238    ///
239    /// Observers are grouped by key and all observers will the same key are assumed to have
240    /// received the latest state update. If an observer with a previously unseen key subscribes,
241    /// it is immediately notified to the stated. If an observer with a known key subscribes, it
242    /// will only be notified when the state is updated since last sent to an observer with the same
243    /// key. All unresolved observers will be resolved to the same value immediately after the state
244    /// is updated. If there is no stored state, then the notification will be delayed until an
245    /// update is made.
246    ///
247    /// Returns `observer` on error.
248    pub fn subscribe(&mut self, key: K, observer: O) -> Result<(), O> {
249        let entry = self.observers.entry(key).or_insert_with(Window::new);
250        entry.observe(observer, &self.notify, self.state.as_ref())
251    }
252
253    /// Deregister all observers that subscribed with `key`. If an observer is subsequently
254    /// subscribed with the same `key` value, it will be treated as a previously unseen `key`.
255    pub fn unsubscribe(&mut self, key: K) {
256        drop(self.observers.remove(&key));
257    }
258}
259
260/// Window tracks all observers for a given `key` and whether their view of the state is
261/// `dirty` or not.
262struct Window<O> {
263    dirty: bool,
264    observer: Option<O>,
265}
266
267impl<O> Window<O> {
268    /// Create a new `Window` without an `observer` and an initial `dirty` value of `true`.
269    pub fn new() -> Self {
270        Window { dirty: true, observer: None }
271    }
272
273    /// Register a new observer. The observer will be notified immediately if the `Window`
274    /// has a dirty view of the state. The observer will be stored for future notification
275    /// if the `Window` does not have a dirty view.
276    ///
277    /// Returns `Err(observer)` if the window already has an observer.
278    pub fn observe<S>(
279        &mut self,
280        observer: O,
281        f: impl Fn(&S, O) -> bool,
282        current_state: Option<&S>,
283    ) -> Result<(), O> {
284        if self.observer.is_some() {
285            return Err(observer);
286        }
287        self.observer = Some(observer);
288        if let Some(current_state) = current_state {
289            if self.dirty {
290                self.notify(f, current_state);
291            }
292        }
293        Ok(())
294    }
295
296    /// Notify the observer _if and only if_ the `Window` has a dirty view of `state`.
297    /// If an observer was present and notified, the `Window` no longer has a dirty view
298    /// after this method returns.
299    pub fn notify<S>(&mut self, f: impl Fn(&S, O) -> bool, state: &S) {
300        match self.observer.take() {
301            Some(observer) => {
302                if f(state, observer) {
303                    self.dirty = false;
304                }
305            }
306            None => self.dirty = true,
307        }
308    }
309}
310
311/// Submodule used to keep the internals of `Key`s and `Generator`s inaccessable.
312mod subscriber_key {
313    /// Manages the creation and distribution of unique `Key`s
314    pub struct Generator {
315        next: Key,
316    }
317
318    impl Default for Generator {
319        fn default() -> Self {
320            Self { next: Key(0) }
321        }
322    }
323
324    impl Generator {
325        /// Get a unique key.
326        /// Returns `None` if 2^64-2 keys have already been generated.
327        pub fn next(&mut self) -> Option<Key> {
328            let key = self.next.clone();
329            if let Some(next) = self.next.0.checked_add(1) {
330                self.next.0 = next;
331                Some(key)
332            } else {
333                None
334            }
335        }
336    }
337
338    /// An internal per-subscriber key that is intended to be unique.
339    #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
340    pub struct Key(u64);
341}
342
343#[cfg(test)]
344mod tests {
345    use super::*;
346    use crate::PollExt;
347    use crate::hanging_get::test_util::TestObserver;
348    use fuchsia_async as fasync;
349    use futures::channel::oneshot;
350
351    #[test]
352    fn subscriber_key_generator_creates_unique_keys() {
353        let mut generator = subscriber_key::Generator::default();
354        let key1 = generator.next();
355        let key2 = generator.next();
356        assert!(key1 != key2);
357    }
358
359    #[test]
360    fn window_add_first_observer_notifies() {
361        let state = 0;
362        let mut window = Window::new();
363        window
364            .observe(TestObserver::expect_value(state), TestObserver::observe, Some(&state))
365            .unwrap();
366    }
367
368    #[test]
369    fn window_none_state_does_not_notify() {
370        let mut window = Window::new();
371        window
372            .observe::<i32>(TestObserver::expect_no_value(), TestObserver::observe, None)
373            .unwrap();
374    }
375
376    #[test]
377    fn window_add_second_observer_does_not_notify() {
378        let state = 0;
379        let mut window = Window::new();
380        window
381            .observe(TestObserver::expect_value(state), TestObserver::observe, Some(&state))
382            .unwrap();
383
384        // Second observer added without updating the value
385        window
386            .observe(TestObserver::expect_no_value(), TestObserver::observe, Some(&state))
387            .unwrap();
388    }
389
390    #[test]
391    fn window_add_second_observer_notifies_after_notify_call() {
392        let mut state = 0;
393        let mut window = Window::new();
394        window
395            .observe(TestObserver::expect_value(state), TestObserver::observe, Some(&state))
396            .unwrap();
397
398        state = 1;
399        window.notify(TestObserver::observe, &state);
400
401        // Second observer added without updating the value
402        window
403            .observe(TestObserver::expect_value(state), TestObserver::observe, Some(&state))
404            .unwrap();
405    }
406
407    #[test]
408    fn window_add_multiple_observers_are_notified() {
409        let mut state = 0;
410        let mut window = Window::new();
411        window
412            .observe(TestObserver::expect_value(state), TestObserver::observe, Some(&state))
413            .unwrap();
414
415        // Second observer added without updating the value
416        let o1 = TestObserver::expect_value(1);
417        let o2 = TestObserver::expect_no_value();
418        window.observe(o1.clone(), TestObserver::observe, Some(&state)).unwrap();
419        let result = window.observe(o2.clone(), TestObserver::observe, Some(&state));
420        assert_eq!(result, Err(o2));
421        assert!(!o1.has_value());
422        state = 1;
423        window.notify(TestObserver::observe, &state);
424    }
425
426    #[test]
427    fn window_dirty_flag_state() {
428        let state = 0;
429        let mut window = Window::new();
430        let o = TestObserver::expect_value(state);
431        window.observe(o, TestObserver::observe, Some(&state)).unwrap();
432        assert!(window.observer.is_none());
433        assert!(!window.dirty);
434        window.notify(TestObserver::observe, &state);
435        assert!(window.dirty);
436        let o = TestObserver::expect_value(state);
437        window.observe(o, TestObserver::observe, Some(&state)).unwrap();
438        assert!(!window.dirty);
439    }
440
441    #[test]
442    fn window_dirty_flag_respects_consumed_flag() {
443        let state = 0;
444        let mut window = Window::new();
445
446        let o = TestObserver::expect_value(state);
447        window.observe(o, TestObserver::observe_incomplete, Some(&state)).unwrap();
448        assert!(window.dirty);
449    }
450
451    #[test]
452    fn hanging_get_inner_subscribe() {
453        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
454        let o = TestObserver::expect_value(0);
455        assert!(!o.has_value());
456        hanging.subscribe(0, o.clone()).unwrap();
457    }
458
459    #[test]
460    fn hanging_get_inner_subscribe_then_set() {
461        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
462        let o = TestObserver::expect_value(0);
463        hanging.subscribe(0, o.clone()).unwrap();
464
465        // No change without a new subscription
466        hanging.set(1);
467    }
468
469    #[test]
470    fn hanging_get_inner_subscribe_twice_then_set() {
471        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
472        hanging.subscribe(0, TestObserver::expect_value(0)).unwrap();
473
474        hanging.subscribe(0, TestObserver::expect_value(1)).unwrap();
475        hanging.set(1);
476    }
477
478    #[test]
479    fn hanging_get_inner_subscribe_multiple_then_set() {
480        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
481        hanging.subscribe(0, TestObserver::expect_value(0)).unwrap();
482
483        // A second subscription with the same client key should not be notified
484        let o2 = TestObserver::expect_value(1);
485        hanging.subscribe(0, o2.clone()).unwrap();
486        assert!(!o2.has_value());
487
488        // A third subscription will queue up along the other waiting observer
489        let _ = hanging.subscribe(0, TestObserver::expect_no_value()).unwrap_err();
490
491        // Set should notify all observers to the change
492        hanging.set(1);
493    }
494
495    #[test]
496    fn hanging_get_inner_subscribe_with_two_clients_then_set() {
497        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
498        hanging.subscribe(0, TestObserver::expect_value(0)).unwrap();
499        hanging.subscribe(0, TestObserver::expect_value(1)).unwrap();
500        hanging.subscribe(1, TestObserver::expect_value(0)).unwrap();
501        hanging.subscribe(1, TestObserver::expect_value(1)).unwrap();
502        hanging.set(1);
503    }
504
505    #[test]
506    fn hanging_get_inner_unsubscribe() {
507        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
508        hanging.subscribe(0, TestObserver::expect_value(0)).unwrap();
509        hanging.subscribe(0, TestObserver::expect_no_value()).unwrap();
510        hanging.unsubscribe(0);
511        hanging.set(1);
512    }
513
514    #[test]
515    fn hanging_get_inner_unsubscribe_one_of_many() {
516        let mut hanging = HangingGetInner::new(Some(0), TestObserver::observe);
517
518        hanging.subscribe(0, TestObserver::expect_value(0)).unwrap();
519        hanging.subscribe(0, TestObserver::expect_no_value()).unwrap();
520        hanging.subscribe(1, TestObserver::expect_value(0)).unwrap();
521        hanging.subscribe(1, TestObserver::expect_no_value()).unwrap();
522
523        // Unsubscribe one of the two observers
524        hanging.unsubscribe(0);
525        assert!(!hanging.observers.contains_key(&0));
526        assert!(hanging.observers.contains_key(&1));
527    }
528
529    #[test]
530    fn hanging_get_inner_delayed_subscribe() {
531        let mut hanging = HangingGetInner::new(None, TestObserver::<u8>::observe);
532        let o = TestObserver::expect_no_value();
533        assert!(!o.has_value());
534        hanging.subscribe(0, o.clone()).unwrap();
535    }
536
537    #[test]
538    fn hanging_get_inner_delayed_subscribe_then_set() {
539        let mut hanging = HangingGetInner::new(None, TestObserver::observe);
540        let o = TestObserver::expect_value(1);
541        hanging.subscribe(0, o.clone()).unwrap();
542
543        // Initial value now set.
544        hanging.set(1);
545    }
546
547    #[test]
548    fn hanging_get_inner_delayed_subscribe_twice_then_set() {
549        let mut hanging = HangingGetInner::new(None, TestObserver::observe);
550        hanging.subscribe(0, TestObserver::expect_value(1)).unwrap();
551
552        // Since the first result is delayed, subscribing again is an error.
553        let o = TestObserver::expect_no_value();
554        let result = hanging.subscribe(0, o.clone());
555        assert_eq!(result, Err(o));
556        hanging.set(1);
557    }
558
559    #[test]
560    fn hanging_get_inner_delayed_subscribe_multiple_then_set() {
561        let mut hanging = HangingGetInner::new(None, TestObserver::observe);
562        hanging.subscribe(0, TestObserver::expect_value(1)).unwrap();
563
564        // A second subscription with the same client key should fail while the subscription hasn't
565        // been notified
566        let o2 = TestObserver::expect_no_value();
567        let result = hanging.subscribe(0, o2.clone());
568        assert_eq!(result, Err(o2.clone()));
569        assert!(!o2.has_value());
570
571        // A third subscription will also fail for the same reason.
572        let o3 = TestObserver::expect_no_value();
573        let result = hanging.subscribe(0, o3.clone());
574        assert_eq!(result, Err(o3));
575
576        // Set should notify all observers to the change
577        hanging.set(1);
578    }
579
580    #[test]
581    fn hanging_get_inner_delayed_subscribe_with_two_clients_then_set() {
582        let mut hanging = HangingGetInner::new(None, TestObserver::observe);
583        hanging.subscribe(0, TestObserver::expect_value(1)).unwrap();
584        let o = TestObserver::expect_no_value();
585        let result = hanging.subscribe(0, o.clone());
586        assert_eq!(result, Err(o));
587        hanging.subscribe(1, TestObserver::expect_value(1)).unwrap();
588        let o2 = TestObserver::expect_no_value();
589        let result = hanging.subscribe(1, o2.clone());
590        assert_eq!(result, Err(o2));
591        hanging.set(1);
592    }
593
594    #[test]
595    fn hanging_get_inner_delayed_unsubscribe() {
596        let mut hanging = HangingGetInner::new(None, TestObserver::observe);
597        hanging.subscribe(0, TestObserver::expect_no_value()).unwrap();
598        let o = TestObserver::expect_no_value();
599        let result = hanging.subscribe(0, o.clone());
600        assert_eq!(result, Err(o));
601        hanging.unsubscribe(0);
602        hanging.set(1);
603    }
604
605    #[test]
606    fn hanging_get_inner_delayed_unsubscribe_one_of_many() {
607        let mut hanging = HangingGetInner::new(None, TestObserver::observe);
608
609        hanging.subscribe(0, TestObserver::<i32>::expect_no_value()).unwrap();
610        let o = TestObserver::expect_no_value();
611        let result = hanging.subscribe(0, o.clone());
612        assert_eq!(result, Err(o));
613        hanging.subscribe(1, TestObserver::expect_no_value()).unwrap();
614        let o2 = TestObserver::expect_no_value();
615        let result = hanging.subscribe(1, o2.clone());
616        assert_eq!(result, Err(o2));
617
618        // Unsubscribe one of the two observers
619        hanging.unsubscribe(0);
620        assert!(!hanging.observers.contains_key(&0));
621        assert!(hanging.observers.contains_key(&1));
622    }
623
624    #[test]
625    fn sync_pub_sub_updates_and_observes() {
626        let mut ex = fasync::TestExecutor::new();
627        let mut broker = HangingGet::new(0i32, |s, o: oneshot::Sender<_>| {
628            o.send(s.clone()).map(|()| true).unwrap()
629        });
630        let publisher = broker.new_publisher();
631        let subscriber = broker.new_subscriber();
632
633        // Initial observation is immediate
634        let (sender, mut receiver) = oneshot::channel();
635        subscriber.register(sender).unwrap();
636        let observation =
637            ex.run_until_stalled(&mut receiver).expect("received initial observation");
638        assert_eq!(observation, Ok(0));
639
640        // Subsequent observations do not happen until after an update
641        let (sender, mut receiver) = oneshot::channel();
642        subscriber.register(sender).unwrap();
643        assert!(ex.run_until_stalled(&mut receiver).is_pending());
644
645        publisher.set(1);
646
647        let observation =
648            ex.run_until_stalled(&mut receiver).expect("received subsequent observation");
649        assert_eq!(observation, Ok(1));
650    }
651
652    #[test]
653    fn sync_pub_sub_multiple_subscribers() {
654        let mut ex = fasync::TestExecutor::new();
655        let mut broker = HangingGet::new(0i32, |s, o: oneshot::Sender<_>| {
656            o.send(s.clone()).map(|()| true).unwrap()
657        });
658        let publisher = broker.new_publisher();
659
660        let sub1 = broker.new_subscriber();
661        let sub2 = broker.new_subscriber();
662
663        // Initial observation for subscribers is immediate
664        let (sender, mut receiver) = oneshot::channel();
665        sub1.register(sender).unwrap();
666        let observation =
667            ex.run_until_stalled(&mut receiver).expect("received initial observation");
668        assert_eq!(observation, Ok(0));
669
670        let (sender, mut receiver) = oneshot::channel();
671        sub2.register(sender).unwrap();
672        let observation =
673            ex.run_until_stalled(&mut receiver).expect("received initial observation");
674        assert_eq!(observation, Ok(0));
675
676        // Subsequent observations do not happen until after an update
677        let (sender, mut recv1) = oneshot::channel();
678        sub1.register(sender).unwrap();
679        assert!(ex.run_until_stalled(&mut recv1).is_pending());
680
681        let (sender, mut recv2) = oneshot::channel();
682        sub2.register(sender).unwrap();
683        assert!(ex.run_until_stalled(&mut recv2).is_pending());
684
685        publisher.set(1);
686        let obs1 =
687            ex.run_until_stalled(&mut recv1).expect("receiver 1 received subsequent observation");
688        assert_eq!(obs1, Ok(1));
689        let obs2 =
690            ex.run_until_stalled(&mut recv2).expect("receiver 2 received subsequent observation");
691        assert_eq!(obs2, Ok(1));
692    }
693
694    #[test]
695    fn sync_pub_sub_delayed_updates_and_observes() {
696        let mut ex = fasync::TestExecutor::new();
697        let mut broker = HangingGet::<i32, _, _>::new_unknown_state(|s, o: oneshot::Sender<_>| {
698            o.send(s.clone()).map(|()| true).unwrap()
699        });
700        let publisher = broker.new_publisher();
701        let subscriber = broker.new_subscriber();
702
703        // Initial observation is delayed due to lack of initial state.
704        let (sender, mut recv1) = oneshot::channel();
705        subscriber.register(sender).unwrap();
706        assert!(ex.run_until_stalled(&mut recv1).is_pending());
707
708        // Subsequent registration fails since the original registration is still pending its
709        // observation.
710        let (sender, mut receiver) = oneshot::channel();
711        assert!(subscriber.register(sender).is_err());
712        assert!(ex.run_until_stalled(&mut receiver).expect("sender closed").is_err());
713
714        // Initial observation received now that the initial value is set.
715        publisher.set(1);
716
717        let observation =
718            ex.run_until_stalled(&mut recv1).expect("received subsequent observation");
719        assert_eq!(observation, Ok(1));
720    }
721
722    #[test]
723    fn sync_pub_sub_delayed_multiple_subscribers() {
724        let mut ex = fasync::TestExecutor::new();
725        let mut broker = HangingGet::<i32, _, _>::new_unknown_state(|s, o: oneshot::Sender<_>| {
726            o.send(s.clone()).map(|()| true).unwrap()
727        });
728        let publisher = broker.new_publisher();
729
730        let sub1 = broker.new_subscriber();
731        let sub2 = broker.new_subscriber();
732
733        // Initial observation for subscribers delayed due to lack of initial state.
734        let (sender, mut recv1) = oneshot::channel();
735        sub1.register(sender).unwrap();
736        assert!(ex.run_until_stalled(&mut recv1).is_pending());
737
738        let (sender, mut recv2) = oneshot::channel();
739        sub2.register(sender).unwrap();
740        assert!(ex.run_until_stalled(&mut recv2).is_pending());
741
742        // Subsequent registrations fails since the original registrations are still pending their
743        // observations.
744        let (sender, mut recv3) = oneshot::channel();
745        assert!(sub1.register(sender).is_err());
746        assert!(ex.run_until_stalled(&mut recv3).expect("sender 3 closed").is_err());
747
748        let (sender, mut recv4) = oneshot::channel();
749        assert!(sub2.register(sender).is_err());
750        assert!(ex.run_until_stalled(&mut recv4).expect("sender 4 closed").is_err());
751
752        // Initial observations received now that initial value is set.
753        publisher.set(1);
754        let obs1 =
755            ex.run_until_stalled(&mut recv1).expect("receiver 1 received subsequent observation");
756        assert_eq!(obs1, Ok(1));
757        let obs2 =
758            ex.run_until_stalled(&mut recv2).expect("receiver 2 received subsequent observation");
759        assert_eq!(obs2, Ok(1));
760    }
761
762    #[test]
763    fn subscriber_drop_unsubscribes() {
764        let mut broker = HangingGet::new(0i32, |s, o: oneshot::Sender<_>| {
765            o.send(s.clone()).map(|()| true).unwrap()
766        });
767        let subscriber = broker.new_subscriber();
768        assert_eq!(broker.inner.lock().observers.len(), 0);
769
770        let (sender, _receiver) = oneshot::channel();
771        subscriber.register(sender).unwrap();
772        assert_eq!(broker.inner.lock().observers.len(), 1);
773
774        drop(subscriber);
775        assert_eq!(broker.inner.lock().observers.len(), 0);
776    }
777}