diff --git a/CHANGELOG.md b/CHANGELOG.md index 087014c..8487be5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ All notable changes to this project will be documented in this file. ### Improvements +* Allow `watch::channel` to store non-`Clone` values for publication and change notification; only owning reads through `Receiver::get` and `Receiver::recv` require `Clone`. * Finish releasing buffered bounded MPSC messages even if one message destructor panics. * Improve unbounded MPSC throughput with batched receiving and incremental storage reclamation; empty-buffer retention is bounded independently of previous peak occupancy. * Make completed and abandoned `Completion` waits lock-free while preserving cancellable pending registration. diff --git a/asyncband/src/watch/mod.rs b/asyncband/src/watch/mod.rs index 54b770a..92aab71 100644 --- a/asyncband/src/watch/mod.rs +++ b/asyncband/src/watch/mod.rs @@ -90,7 +90,7 @@ use crate::internal::wakerset::WakerToken; /// let (_tx, rx) = watch::channel("ready"); /// assert_eq!(rx.get(), "ready"); /// ``` -pub fn channel(initial: T) -> (Sender, Receiver) { +pub fn channel(initial: T) -> (Sender, Receiver) { let shared = Arc::new(Shared { state: Mutex::new(State { value: initial, diff --git a/tests-integration/tests/watch_test.rs b/tests-integration/tests/watch_test.rs index 994eda0..2636e77 100644 --- a/tests-integration/tests/watch_test.rs +++ b/tests-integration/tests/watch_test.rs @@ -59,6 +59,8 @@ impl Clone for PanicOnceClone { } } +struct NonClone(usize); + #[test] fn initial_value_is_observed_and_updates_coalesce() { let (tx, mut rx) = watch::channel(0); @@ -147,6 +149,22 @@ fn subscriptions_start_at_the_current_version() { assert_eq!(FutureExt::block_on(subscribed.recv()).unwrap(), 2); } +#[test] +fn non_clone_values_support_publication_and_change_tracking() { + let (tx, mut rx) = watch::channel(NonClone(0)); + + assert_eq!(rx.has_changed(), Ok(false)); + + tx.send(NonClone(1)).unwrap(); + assert_eq!(rx.has_changed(), Ok(true)); + FutureExt::block_on(rx.changed()).unwrap(); + assert_eq!(rx.has_changed(), Ok(false)); + + let previous = tx.send_replace(NonClone(2)); + assert_eq!(previous.0, 1); + assert_eq!(rx.has_changed(), Ok(true)); +} + #[test] fn final_unseen_value_is_reported_before_disconnection() { let (tx, mut first) = watch::channel(0);