Skip to content

feat(watch): add a latest-state channel - #233

Open
QwQBiG wants to merge 1 commit into
apache:mainfrom
QwQBiG:feat/watch-channel
Open

feat(watch): add a latest-state channel#233
QwQBiG wants to merge 1 commit into
apache:mainfrom
QwQBiG:feat/watch-channel

Conversation

@QwQBiG

@QwQBiG QwQBiG commented Aug 28, 2026

Copy link
Copy Markdown

Summary

  • add an opt-in asyncband::watch latest-state channel with cloneable senders and independently versioned receivers
  • retain one current value, coalesce intermediate updates, keep borrow non-consuming, and drain a final unseen value before reporting disconnection
  • make changed cancellation safe and release replaced values, retired wakers, and wake callbacks outside the internal lock
  • add contract and trait tests, public documentation, self-benchmarks, and Tokio 1.53.1 ecosystem comparisons

Closes #215.

Design Notes

The public API returns owning Arc<T> snapshots from borrow, borrow_and_update, and changed. Unlike Tokio's lock-backed Ref<T> and changed() -> Result<(), _> API, these snapshots never retain the channel's internal lock and may be stored or moved independently. The ecosystem benchmark documents this semantic difference and immediately reads the current usize value on both sides.

The implementation retains an Arc<T>, a monotonically checked version, endpoint counts, and a WaitSet under one private mutex. Each receiver stores its own observed version. New subscriptions begin at the current version, while receiver clones inherit the source receiver's observed version and then advance independently.

The internal arena, mutex, and waitset feature gates include watch because of the watch -> WaitSet -> Arena dependency chain and watch's direct use of the internal mutex. These additions are additive and do not change any existing feature combination or public behavior.

WaitSet::is_empty() lets the watch send and final-sender-drop paths avoid taking an empty waker set. Besides avoiding unnecessary work, this skips the internal epoch advance performed by take_wakers() when no waiter exists.

The benchmarks cover current-value borrowing, send-and-borrow paths, ready changes, pending notification, and 1/2/4/8/32-receiver fanout. No measured watch path showed a sustained regression above 3x relative to Tokio on the development machine.

Validation included cargo x build --locked, cargo x check, cargo x test --no-capture, cargo x bench, Rust 1.86 watch-only all-target checks, nightly Clippy and rustfmt, typos, Hawkeye license checks, and all-features rustdoc with warnings denied.

@QwQBiG

QwQBiG commented Aug 28, 2026

Copy link
Copy Markdown
Author

Hi @tisonkun, PR #233 for #215 is ready for review. The workflow is currently awaiting maintainer approval because the PR comes from a fork. Could you please approve it when convenient? Thank you! (^•ω•^)

@QwQBiG

QwQBiG commented Aug 28, 2026

Copy link
Copy Markdown
Author

All 9 CI checks passed.
Fun coincidence that this PR number is also 233 😄
Ready for review whenever you have time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(watch): add a latest-state channel

1 participant