+
+ #[test]
+ #[cfg(feature = "std")]
+ fn test_multi_future_sleep() {
+ // Tests the `Sleeper` with multiple futures.
+ let notifier_a = Notifier::new();
+ let notifier_b = Notifier::new();
+
+ // Set both notifiers as woken without sleeping yet.
+ notifier_a.notify();
+ notifier_b.notify();
+ Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future()).wait();
+
+ // One future has woken us up, but the other should still have a pending notification.
+ Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future()).wait();
+
+ // However once we've slept twice, we should no longer have any pending notifications
+ assert!(!Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future())
+ .wait_timeout(Duration::from_millis(10)));
+
+ // Test ordering somewhat more.
+ notifier_a.notify();
+ Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future()).wait();
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn sleeper_with_pending_callbacks() {
+ // This is similar to the above `test_multi_future_sleep` test, but in addition registers
+ // "normal" callbacks which will cause the futures to assume notification has occurred,
+ // rather than waiting for a woken sleeper.
+ let notifier_a = Notifier::new();
+ let notifier_b = Notifier::new();
+
+ // Set both notifiers as woken without sleeping yet.
+ notifier_a.notify();
+ notifier_b.notify();
+
+ // After sleeping one future (not guaranteed which one, however) will have its notification
+ // bit cleared.
+ Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future()).wait();
+
+ // By registering a callback on the futures for both notifiers, one will complete
+ // immediately, but one will remain tied to the notifier, and will complete once the
+ // notifier is next woken, which will be considered the completion of the notification.
+ let callback_a = Arc::new(AtomicBool::new(false));
+ let callback_b = Arc::new(AtomicBool::new(false));
+ let callback_a_ref = Arc::clone(&callback_a);
+ let callback_b_ref = Arc::clone(&callback_b);
+ notifier_a.get_future().register_callback(Box::new(move || assert!(!callback_a_ref.fetch_or(true, Ordering::SeqCst))));
+ notifier_b.get_future().register_callback(Box::new(move || assert!(!callback_b_ref.fetch_or(true, Ordering::SeqCst))));
+ assert!(callback_a.load(Ordering::SeqCst) ^ callback_b.load(Ordering::SeqCst));
+
+ // If we now notify both notifiers again, the other callback will fire, completing the
+ // notification, and we'll be back to one pending notification.
+ notifier_a.notify();
+ notifier_b.notify();
+
+ assert!(callback_a.load(Ordering::SeqCst) && callback_b.load(Ordering::SeqCst));
+ Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future()).wait();
+ assert!(!Sleeper::from_two_futures(¬ifier_a.get_future(), ¬ifier_b.get_future())
+ .wait_timeout(Duration::from_millis(10)));
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn multi_poll_stores_single_waker() {
+ // When a `Future` is `poll()`ed multiple times, only the last `Waker` should be called,
+ // but previously we'd store all `Waker`s until they're all woken at once. This tests a few
+ // cases to ensure `Future`s avoid storing an endless set of `Waker`s.
+ let notifier = Notifier::new();
+ let future_state = Arc::clone(¬ifier.get_future().state);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 0);
+
+ // Test that simply polling a future twice doesn't result in two pending `Waker`s.
+ let mut future_a = notifier.get_future();
+ assert_eq!(Pin::new(&mut future_a).poll(&mut Context::from_waker(&create_waker().1)), Poll::Pending);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 1);
+ assert_eq!(Pin::new(&mut future_a).poll(&mut Context::from_waker(&create_waker().1)), Poll::Pending);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 1);
+
+ // If we poll a second future, however, that will store a second `Waker`.
+ let mut future_b = notifier.get_future();
+ assert_eq!(Pin::new(&mut future_b).poll(&mut Context::from_waker(&create_waker().1)), Poll::Pending);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 2);
+
+ // but when we drop the `Future`s, the pending Wakers will also be dropped.
+ mem::drop(future_a);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 1);
+ mem::drop(future_b);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 0);
+
+ // Further, after polling a future twice, if the notifier is woken all Wakers are dropped.
+ let mut future_a = notifier.get_future();
+ assert_eq!(Pin::new(&mut future_a).poll(&mut Context::from_waker(&create_waker().1)), Poll::Pending);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 1);
+ assert_eq!(Pin::new(&mut future_a).poll(&mut Context::from_waker(&create_waker().1)), Poll::Pending);
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 1);
+ notifier.notify();
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 0);
+ assert_eq!(Pin::new(&mut future_a).poll(&mut Context::from_waker(&create_waker().1)), Poll::Ready(()));
+ assert_eq!(future_state.lock().unwrap().std_future_callbacks.len(), 0);
+ }