Skip to main content

nuclei/sync/
watch.rs

1//! A multi-producer, multi-consumer channel that retains only the *last* sent
2//! value.
3//!
4//! [`channel`] returns a [`Sender`] and a [`Receiver`] around an initial
5//! value. Each [`Receiver`] tracks the last value *seen* by its own caller.
6//! The API is the established async watch-channel API; nothing here needs a
7//! runtime.
8//!
9//! - [`Receiver::borrow_and_update`] returns the current value and marks it
10//!   seen. [`Receiver::borrow`] returns it without marking it seen.
11//! - [`Receiver::changed`] completes when a value the receiver has not seen
12//!   is in the channel, and marks it seen. At creation the initial value is
13//!   seen, and a receiver made by [`Sender::subscribe`] sees the value that
14//!   was current at that moment as seen.
15//! - [`Receiver::has_changed`] is the synchronous check; it errors if and
16//!   only if the channel is closed, while `changed` errors only when the
17//!   channel is closed *and* the current value is seen.
18//! - [`Sender::is_closed`] and [`Sender::closed`] tell the producer that
19//!   every [`Receiver`] is gone. The value is dropped when every sender and
20//!   every receiver is gone.
21//!
22//! ```
23//! use nuclei::sync::watch;
24//!
25//! let (tx, mut rx) = watch::channel("hello");
26//! assert_eq!(*rx.borrow_and_update(), "hello");
27//! assert!(!rx.has_changed().unwrap());
28//!
29//! tx.send("world").unwrap();
30//! assert!(rx.has_changed().unwrap());
31//! assert_eq!(*rx.borrow_and_update(), "world");
32//! ```
33//!
34//! # The value lives in an `Atom`
35//!
36//! Where a lock-based channel guards the value with a read-write lock, this
37//! one keeps it in an [`Atom`]. A send publishes a new allocation with
38//! one swap; a borrow is one protected load and never blocks a sender, and a
39//! sender never blocks a borrow. Two consequences follow, and both differ
40//! from the lock-based API:
41//!
42//! - The channel needs `T: Send + Sync + 'static`: values are shared by
43//!   reference between threads and reclaimed later.
44//! - A [`Ref`] does not hold a lock but a reclamation guard. A value that was
45//!   replaced stays allocated until every `Ref` that can see it is dropped,
46//!   so keep a `Ref` short. It is `!Send`: it must be dropped on the thread
47//!   that took it, and the compiler therefore refuses to hold one across an
48//!   await in a task that may move threads.
49//! - The old value cannot be handed back by value while readers may still
50//!   look at it, so [`Sender::send_replace`] returns a *clone* (`T: Clone`),
51//!   and the two in-place modifiers, [`Sender::send_modify`] and
52//!   [`Sender::send_if_modified`], work on a clone too: they copy the value,
53//!   let the closure change the copy and publish it with a
54//!   compare-and-swap, retrying on a racing sender. Their closures are
55//!   `FnMut` and may run more than once. A closure that panics, or that
56//!   returns `false` from `send_if_modified`, publishes nothing, and the
57//!   channel keeps the value it had.
58//!
59//! # Progress
60//!
61//! - Wait-free (a bounded number of the caller's own steps whatever other
62//!   threads do): [`Receiver::borrow`], [`Receiver::borrow_and_update`],
63//!   [`Receiver::has_changed`], [`Receiver::is_closed`],
64//!   [`Receiver::mark_changed`], [`Receiver::mark_unchanged`],
65//!   [`Sender::borrow`], [`Sender::is_closed`], [`Sender::subscribe`],
66//!   [`Sender::receiver_count`], [`Sender::sender_count`], both `same_channel`
67//!   checks, the clones, and dropping a [`Ref`]. A borrow is an `Atom`
68//!   load, which is wait-free.
69//! - The *publication* of [`Sender::send`] and [`Sender::send_replace`] (the
70//!   swap and the version bump) is wait-free, but each ends by waking the
71//!   waiting receivers through [`Notify::notify_waiters`](super::Notify),
72//!   which is lock-free: it takes the queue's drain role with a
73//!   compare-and-swap, or leaves a mark for the thread that holds it, and a
74//!   pass may serve waiters other threads queue meanwhile. So `send` and
75//!   `send_replace` are lock-free, not wait-free. So is dropping the last
76//!   sender or the last receiver, for the same wake.
77//! - [`Sender::send_modify`] and [`Sender::send_if_modified`] are lock-free:
78//!   they retry the compare-and-swap whenever another sender published
79//!   first, so a call can be delayed without bound by other senders' progress,
80//!   and each retry runs the closure again.
81//! - Polling [`Receiver::changed`], [`Receiver::wait_for`] and
82//!   [`Sender::closed`] is lock-free: a poll may queue a waiter, which is a
83//!   lock-free queue operation.
84
85#![allow(unsafe_code)]
86
87use core::fmt;
88use core::ops::Deref;
89
90use kovan::{Atom, AtomGuard, CachePadded};
91
92use super::Notify;
93use super::internal::{Arc, AtomicU64, AtomicUsize, Ordering};
94
95use self::error::{RecvError, SendError};
96
97/// The low bit of the state word: every sender is gone.
98const CLOSED: u64 = 1;
99/// One send. Two keeps [`CLOSED`] out of the version.
100const STEP: u64 = 2;
101
102/// The version part of a state word.
103fn version_of(state: u64) -> u64 {
104    state & !CLOSED
105}
106
107pub mod error {
108    //! Error types of the watch channel.
109
110    use core::fmt;
111    use std::error::Error;
112
113    /// Error produced when sending a value fails: every receiver is gone.
114    ///
115    /// The value is handed back in the error.
116    #[derive(PartialEq, Eq, Clone, Copy)]
117    pub struct SendError<T>(pub T);
118
119    impl<T> fmt::Debug for SendError<T> {
120        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121            f.debug_struct("SendError").finish_non_exhaustive()
122        }
123    }
124
125    impl<T> fmt::Display for SendError<T> {
126        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
127            write!(fmt, "channel closed")
128        }
129    }
130
131    impl<T> Error for SendError<T> {}
132
133    /// Error produced when receiving a change notification: every sender is
134    /// gone.
135    #[derive(Debug, Clone)]
136    pub struct RecvError(pub(super) ());
137
138    impl fmt::Display for RecvError {
139        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
140            write!(fmt, "channel closed")
141        }
142    }
143
144    impl Error for RecvError {}
145}
146
147struct Shared<T: Send + Sync + 'static> {
148    /// The most recent value.
149    value: Atom<T>,
150    /// The version in the high bits, [`CLOSED`] in the low bit. The version
151    /// moves after the value it counts is published and never before, which
152    /// is what lets a reader pair a version with a value that is at least as
153    /// new. Padded: every send writes it and every borrow reads it.
154    state: CachePadded<AtomicU64>,
155    /// How many [`Receiver`]s exist.
156    ref_count_rx: AtomicUsize,
157    /// How many [`Sender`]s exist.
158    ref_count_tx: AtomicUsize,
159    /// Wakes receivers waiting for a change.
160    notify_rx: Notify,
161    /// Wakes the producer waiting for the receivers to go.
162    notify_tx: Notify,
163}
164
165impl<T: Send + Sync + 'static> Shared<T> {
166    /// A value was just published: count it, then wake the receivers.
167    ///
168    /// The order matters twice. The version moves after the publication so a
169    /// reader that sees the version also finds that value or a newer one
170    /// (see [`Self::snapshot`]), and the wake comes after the version so a
171    /// receiver that was woken finds the new version when it looks (see
172    /// `changed_impl`).
173    fn published(&self) {
174        // Release: pairs with the Acquire loads of the state, publishing the
175        // value written before it.
176        self.state.fetch_add(STEP, Ordering::Release);
177        self.notify_rx.notify_waiters();
178    }
179
180    /// A value and a version that is no newer than it.
181    ///
182    /// The version is read first. It is bumped only after its value is
183    /// published, so the Acquire load of the state makes every publication
184    /// the version counts happen before the load of the value, and the value
185    /// is the newest of those or something newer. The reverse order could
186    /// pair a stale value with a version that already counts a newer one and
187    /// let a receiver mark that newer version seen without ever reading it.
188    /// The cost of this order is that a receiver can read a value one send
189    /// ahead of its version: a harmless extra `changed`, which the docs of
190    /// `Receiver::borrow` warn of.
191    fn snapshot(&self) -> (AtomGuard<'_, T>, u64) {
192        let version = version_of(self.state.load(Ordering::Acquire));
193        (self.value.load(), version)
194    }
195}
196
197impl<T: Send + Sync + 'static + fmt::Debug> fmt::Debug for Shared<T> {
198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199        let state = self.state.load(Ordering::Acquire);
200        f.debug_struct("Shared")
201            .field("value", &*self.value.load())
202            .field("version", &version_of(state))
203            .field("is_closed", &(state & CLOSED != 0))
204            .field("ref_count_rx", &self.ref_count_rx)
205            .finish()
206    }
207}
208
209/// Creates a new watch channel around `init`, returning the send and receive
210/// handles.
211///
212/// All values sent by the [`Sender`] become visible to the [`Receiver`]
213/// handles; only the last value sent is kept, and the ones before it are
214/// dropped. The initial value counts as seen by the first receiver.
215///
216/// ```
217/// use nuclei::sync::watch;
218///
219/// let (tx, rx) = watch::channel(0u32);
220/// tx.send(1).unwrap();
221/// assert_eq!(*rx.borrow(), 1);
222/// ```
223pub fn channel<T: Send + Sync + 'static>(init: T) -> (Sender<T>, Receiver<T>) {
224    let shared = Arc::new(Shared {
225        value: Atom::new(init),
226        state: CachePadded::new(AtomicU64::new(0)),
227        ref_count_rx: AtomicUsize::new(1),
228        ref_count_tx: AtomicUsize::new(1),
229        notify_rx: Notify::new(),
230        notify_tx: Notify::new(),
231    });
232    let tx = Sender {
233        shared: Arc::clone(&shared),
234    };
235    let rx = Receiver { shared, version: 0 };
236    (tx, rx)
237}
238
239/// Sends values to the associated [`Receiver`]s.
240///
241/// Created by [`channel`]. Clone it for more producers. The channel closes
242/// for the receivers when the last sender is dropped.
243///
244/// Requires `T: Send + Sync + 'static`, see the [module docs](self).
245pub struct Sender<T: Send + Sync + 'static> {
246    shared: Arc<Shared<T>>,
247}
248
249/// Receives values from the associated [`Sender`]s.
250///
251/// Created by [`channel`] or [`Sender::subscribe`]; clone it for more
252/// consumers, each with its own record of what it has seen.
253///
254/// Requires `T: Send + Sync + 'static`, see the [module docs](self).
255pub struct Receiver<T: Send + Sync + 'static> {
256    shared: Arc<Shared<T>>,
257    /// The last version this receiver saw.
258    version: u64,
259}
260
261/// A reference to the value inside the channel.
262///
263/// Unlike a lock guard, a `Ref` never blocks a sender. It keeps the value it
264/// points to, and every value replaced since, allocated until it is dropped,
265/// so keep it short. It must be dropped on the thread that took it: it is
266/// not `Send`.
267pub struct Ref<'a, T: Send + Sync + 'static> {
268    guard: AtomGuard<'a, T>,
269    has_changed: bool,
270}
271
272// SAFETY: a shared `&Ref` gives `&T` and a bool. `T: Sync` makes the `&T`
273// safe on any thread, and the reclamation guard inside stays pinned on the
274// thread that owns the `Ref` for as long as the `Ref` lives, so the value
275// outlives every reference a `&Ref` hands out.
276unsafe impl<T: Send + Sync + 'static> Sync for Ref<'_, T> {}
277
278impl<T: Send + Sync + 'static> Ref<'_, T> {
279    /// Whether the borrowed value is considered *changed* since it was last
280    /// marked seen.
281    ///
282    /// Unlike [`Receiver::has_changed`], this does not fail when the channel
283    /// is closed. For a borrow taken from the [`Sender`] it is always
284    /// `false`.
285    ///
286    /// ```
287    /// use nuclei::sync::watch;
288    ///
289    /// let (tx, mut rx) = watch::channel("hello");
290    /// tx.send("goodbye").unwrap();
291    /// assert!(!tx.borrow().has_changed());
292    /// drop(tx);
293    /// assert!(rx.borrow().has_changed());
294    /// assert!(rx.borrow_and_update().has_changed());
295    /// assert!(!rx.borrow().has_changed());
296    /// ```
297    pub fn has_changed(&self) -> bool {
298        self.has_changed
299    }
300}
301
302impl<T: Send + Sync + 'static> Deref for Ref<'_, T> {
303    type Target = T;
304
305    fn deref(&self) -> &T {
306        &self.guard
307    }
308}
309
310impl<T: Send + Sync + 'static + fmt::Debug> fmt::Debug for Ref<'_, T> {
311    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312        f.debug_struct("Ref")
313            .field("value", &**self)
314            .field("has_changed", &self.has_changed)
315            .finish()
316    }
317}
318
319impl<T: Send + Sync + 'static> Receiver<T> {
320    fn from_shared(version: u64, shared: Arc<Shared<T>>) -> Self {
321        // Relaxed: a plain counter; no memory is published through it.
322        shared.ref_count_rx.fetch_add(1, Ordering::Relaxed);
323        Self { shared, version }
324    }
325
326    /// Returns a reference to the most recently sent value.
327    ///
328    /// Does not mark the value seen, so a later [`changed`](Self::changed)
329    /// can return at once even though you have read it. If you wait for
330    /// changes in a loop, prefer [`borrow_and_update`](Self::borrow_and_update).
331    ///
332    /// Wait-free, and it never blocks a sender. A borrow keeps the value it
333    /// points to alive; keep it short and drop it before awaiting.
334    ///
335    /// ```
336    /// use nuclei::sync::watch;
337    ///
338    /// let (_tx, rx) = watch::channel("hello");
339    /// assert_eq!(*rx.borrow(), "hello");
340    /// ```
341    pub fn borrow(&self) -> Ref<'_, T> {
342        let (guard, version) = self.shared.snapshot();
343        Ref {
344            guard,
345            has_changed: self.version != version,
346        }
347    }
348
349    /// Returns a reference to the most recently sent value and marks it seen.
350    ///
351    /// Later calls to [`changed`](Self::changed) do not return until a value
352    /// newer than this one is sent. Wait-free; see [`borrow`](Self::borrow)
353    /// for the advice on holding the reference.
354    ///
355    /// ```
356    /// use nuclei::sync::watch;
357    ///
358    /// let (tx, mut rx) = watch::channel("hello");
359    /// tx.send("goodbye").unwrap();
360    /// assert_eq!(*rx.borrow_and_update(), "goodbye");
361    /// assert!(!rx.has_changed().unwrap());
362    /// ```
363    pub fn borrow_and_update(&mut self) -> Ref<'_, T> {
364        let (guard, version) = self.shared.snapshot();
365        let has_changed = self.version != version;
366        self.version = version;
367        Ref { guard, has_changed }
368    }
369
370    /// Checks whether the channel holds a value this receiver has not seen.
371    /// The value is not marked seen.
372    ///
373    /// It does not compare values: the same value sent twice counts as a
374    /// change.
375    ///
376    /// # Errors
377    ///
378    /// Returns a [`RecvError`] if and only if the channel is closed.
379    ///
380    /// ```
381    /// use nuclei::sync::watch;
382    ///
383    /// let (tx, mut rx) = watch::channel("hello");
384    /// tx.send("goodbye").unwrap();
385    /// assert!(rx.has_changed().unwrap());
386    /// assert_eq!(*rx.borrow_and_update(), "goodbye");
387    /// assert!(!rx.has_changed().unwrap());
388    /// drop(tx);
389    /// assert!(rx.has_changed().is_err());
390    /// ```
391    pub fn has_changed(&self) -> Result<bool, RecvError> {
392        let state = self.shared.state.load(Ordering::Acquire);
393        if state & CLOSED != 0 {
394            return Err(RecvError(()));
395        }
396        Ok(self.version != version_of(state))
397    }
398
399    /// Whether the channel is closed: every [`Sender`] has been dropped.
400    ///
401    /// ```
402    /// use nuclei::sync::watch;
403    ///
404    /// let (tx, rx) = watch::channel(());
405    /// assert!(!rx.is_closed());
406    /// drop(tx);
407    /// assert!(rx.is_closed());
408    /// ```
409    pub fn is_closed(&self) -> bool {
410        self.shared.state.load(Ordering::Acquire) & CLOSED != 0
411    }
412
413    /// Marks the current value as not seen.
414    ///
415    /// Afterwards [`has_changed`](Self::has_changed) is `true` and
416    /// [`changed`](Self::changed) returns at once, whether or not a new value
417    /// is sent. Useful to trigger a first notification after subscribing.
418    pub fn mark_changed(&mut self) {
419        // Wrapping: it must agree with the wrapping `fetch_add` of the sender.
420        self.version = self.version.wrapping_sub(STEP);
421    }
422
423    /// Marks the current value as seen, without reading it.
424    pub fn mark_unchanged(&mut self) {
425        self.version = version_of(self.shared.state.load(Ordering::Acquire));
426    }
427
428    /// Waits for a change notification, then marks the current value as seen.
429    ///
430    /// If the current value has not been seen yet, this marks it seen and
431    /// returns at once. Otherwise it waits until a sender sends a new value
432    /// or the last sender is dropped.
433    ///
434    /// # Errors
435    ///
436    /// Returns a [`RecvError`] if the channel is closed *and* the current
437    /// value is seen.
438    ///
439    /// # Cancel safety
440    ///
441    /// Cancel safe: if the future is dropped before it completes, no value
442    /// was marked seen by it.
443    ///
444    /// ```
445    /// use nuclei::sync::watch;
446    /// use std::future::Future;
447    /// use std::pin::pin;
448    /// use std::task::{Context, Poll, Waker};
449    ///
450    /// let (tx, mut rx) = watch::channel("hello");
451    /// let mut cx = Context::from_waker(Waker::noop());
452    /// let mut changed = pin!(rx.changed());
453    /// assert!(changed.as_mut().poll(&mut cx).is_pending());
454    /// tx.send("goodbye").unwrap();
455    /// assert!(matches!(changed.as_mut().poll(&mut cx), Poll::Ready(Ok(()))));
456    /// ```
457    pub async fn changed(&mut self) -> Result<(), RecvError> {
458        changed_impl(&self.shared, &mut self.version).await
459    }
460
461    /// Waits for a value that satisfies `f`.
462    ///
463    /// Calls `f` on the current value first, even if it is already seen, and
464    /// then on the newest value whenever something is sent. When `f` returns
465    /// `true`, returns a reference to that value and marks it seen. The
466    /// channel keeps only the latest value, so a burst of sends can skip
467    /// values: `f` always sees the newest.
468    ///
469    /// # Errors
470    ///
471    /// Returns a [`RecvError`] if the channel is closed. Then `f` has been
472    /// called on the last value and returned `false` for it.
473    ///
474    /// # Cancel safety
475    ///
476    /// Cancel safe: the last value `f` returned `true` for is never marked
477    /// seen by a dropped call.
478    ///
479    /// # Panics
480    ///
481    /// If and only if `f` panics. Nothing the receiver shares is poisoned.
482    ///
483    /// ```
484    /// use nuclei::sync::watch;
485    /// use std::future::Future;
486    /// use std::pin::pin;
487    /// use std::task::{Context, Poll, Waker};
488    ///
489    /// let (tx, mut rx) = watch::channel(0);
490    /// let mut cx = Context::from_waker(Waker::noop());
491    /// let mut wait = pin!(rx.wait_for(|v| *v == 2));
492    /// assert!(wait.as_mut().poll(&mut cx).is_pending());
493    /// tx.send(1).unwrap();
494    /// assert!(wait.as_mut().poll(&mut cx).is_pending());
495    /// tx.send(2).unwrap();
496    /// match wait.as_mut().poll(&mut cx) {
497    ///     Poll::Ready(Ok(value)) => assert_eq!(*value, 2),
498    ///     _ => panic!("the value 2 was sent"),
499    /// }
500    /// ```
501    pub async fn wait_for(
502        &mut self,
503        mut f: impl FnMut(&T) -> bool,
504    ) -> Result<Ref<'_, T>, RecvError> {
505        let mut closed = false;
506        loop {
507            // A value that fits at once spends one operation of the poll's
508            // budget, as `changed` does.
509            if !crate::coop::has_budget_remaining() {
510                crate::coop::yield_spent().await;
511            }
512            {
513                let (guard, new_version) = self.shared.snapshot();
514                let has_changed = self.version != new_version;
515                self.version = new_version;
516                // After the channel closed, only a value that changed since
517                // `f` last judged is worth another call.
518                if (!closed || has_changed) && f(&guard) {
519                    crate::coop::try_spend();
520                    return Ok(Ref { guard, has_changed });
521                }
522            }
523            if closed {
524                return Err(RecvError(()));
525            }
526            closed = changed_impl(&self.shared, &mut self.version).await.is_err();
527        }
528    }
529
530    /// Whether the two receivers belong to the same channel.
531    ///
532    /// ```
533    /// use nuclei::sync::watch;
534    ///
535    /// let (_tx, rx) = watch::channel(true);
536    /// let rx2 = rx.clone();
537    /// assert!(rx.same_channel(&rx2));
538    /// let (_tx3, rx3) = watch::channel(true);
539    /// assert!(!rx3.same_channel(&rx2));
540    /// ```
541    pub fn same_channel(&self, other: &Self) -> bool {
542        Arc::ptr_eq(&self.shared, &other.shared)
543    }
544}
545
546/// The version after the one `version` records, or the end of the channel.
547fn maybe_changed<T: Send + Sync + 'static>(
548    shared: &Shared<T>,
549    version: &mut u64,
550) -> Option<Result<(), RecvError>> {
551    let state = shared.state.load(Ordering::Acquire);
552    let new_version = version_of(state);
553    if *version != new_version {
554        *version = new_version;
555        return Some(Ok(()));
556    }
557    if state & CLOSED != 0 {
558        return Some(Err(RecvError(())));
559    }
560    None
561}
562
563/// Waits until `maybe_changed` has an answer.
564///
565/// The wait cannot miss a send. The future for the next wake is created
566/// first, and only then is the version read:
567///
568/// - A [`Notified`](super::Notified) hears every `notify_waiters` made after
569///   it was *created*, polled or not.
570/// - A sender bumps the version and only then calls `notify_waiters`.
571///
572/// So take a send. If its version bump is visible to the read below, the read
573/// returns. If it is not, the bump came after the read, and `notify_waiters`,
574/// which is after the bump, came after the creation of the `Notified` (the
575/// read follows the creation in this thread's order, and a `notify_waiters`
576/// seen by the creation would have made the bump visible through its Release
577/// store), so the `Notified` completes. Either way the loop wakes up.
578/// A completion without a new version is a spurious wake, and the loop
579/// looks again.
580async fn changed_impl<T: Send + Sync + 'static>(
581    shared: &Shared<T>,
582    version: &mut u64,
583) -> Result<(), RecvError> {
584    loop {
585        // A change seen at once spends one operation of the poll's budget
586        // (see `coop`): with the budget spent, the look waits for the next
587        // poll, after the shard's other tasks.
588        if !crate::coop::has_budget_remaining() {
589            crate::coop::yield_spent().await;
590        }
591        let notified = shared.notify_rx.notified();
592        if let Some(ret) = maybe_changed(shared, version) {
593            crate::coop::try_spend();
594            return ret;
595        }
596        notified.await;
597    }
598}
599
600impl<T: Send + Sync + 'static> Clone for Receiver<T> {
601    fn clone(&self) -> Self {
602        Self::from_shared(self.version, Arc::clone(&self.shared))
603    }
604}
605
606impl<T: Send + Sync + 'static> Drop for Receiver<T> {
607    fn drop(&mut self) {
608        // Relaxed: the count publishes no memory. A producer waiting in
609        // `closed` reads it after creating its `Notified`, which hears the
610        // wake below, and that wake's Release makes this decrement visible.
611        if self.shared.ref_count_rx.fetch_sub(1, Ordering::Relaxed) == 1 {
612            self.shared.notify_tx.notify_waiters();
613        }
614    }
615}
616
617impl<T: Send + Sync + 'static + fmt::Debug> fmt::Debug for Receiver<T> {
618    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
619        f.debug_struct("Receiver")
620            .field("shared", &*self.shared)
621            .field("version", &self.version)
622            .finish()
623    }
624}
625
626impl<T: Send + Sync + 'static> Sender<T> {
627    /// Creates the sending half of a channel with no receiver yet.
628    ///
629    /// Sending fails until [`subscribe`](Self::subscribe) creates one.
630    ///
631    /// ```
632    /// use nuclei::sync::watch::Sender;
633    ///
634    /// let sender = Sender::new(0u8);
635    /// assert!(sender.send(3).is_err());
636    /// let _rx = sender.subscribe();
637    /// assert!(sender.send(4).is_ok());
638    /// ```
639    pub fn new(init: T) -> Self {
640        channel(init).0
641    }
642
643    /// Sends a new value, notifying all receivers.
644    ///
645    /// Fails if every receiver is gone; the value comes back in the error and
646    /// is not kept for receivers that [`subscribe`](Self::subscribe) later.
647    /// To always make a value available, even with no receiver, use
648    /// [`send_replace`](Self::send_replace), [`send_modify`](Self::send_modify)
649    /// or [`send_if_modified`](Self::send_if_modified).
650    ///
651    /// The publication is wait-free; the wake of the receivers makes the
652    /// whole call lock-free (see the [module docs](self)).
653    ///
654    /// ```
655    /// use nuclei::sync::watch;
656    ///
657    /// let (tx, rx) = watch::channel(1);
658    /// tx.send(2).unwrap();
659    /// assert_eq!(*rx.borrow(), 2);
660    /// drop(rx);
661    /// assert_eq!(tx.send(3).unwrap_err().0, 3);
662    /// ```
663    pub fn send(&self, value: T) -> Result<(), SendError<T>> {
664        // Only a hint: a receiver may come or go right after.
665        if self.receiver_count() == 0 {
666            return Err(SendError(value));
667        }
668        self.shared.value.store(value);
669        self.shared.published();
670        Ok(())
671    }
672
673    /// Modifies the watched value **unconditionally**, notifying all
674    /// receivers.
675    ///
676    /// Also works with no receiver. `modify` runs on a clone of the current
677    /// value, and the clone is published by a compare-and-swap; if another
678    /// sender published first, `modify` runs again on the new value, so it is
679    /// `FnMut`. Prefer [`send_if_modified`](Self::send_if_modified) when the
680    /// value is only sometimes changed.
681    ///
682    /// Lock-free: it retries against other senders.
683    ///
684    /// # Panics
685    ///
686    /// Panics if `modify` (or the clone) panics. Nothing is published then
687    /// and no receiver is notified: the channel keeps the value it had.
688    ///
689    /// ```
690    /// use nuclei::sync::watch;
691    ///
692    /// #[derive(Clone)]
693    /// struct State {
694    ///     counter: usize,
695    /// }
696    /// let (tx, rx) = watch::channel(State { counter: 0 });
697    /// tx.send_modify(|state| state.counter += 1);
698    /// assert_eq!(rx.borrow().counter, 1);
699    /// ```
700    pub fn send_modify<F>(&self, mut modify: F)
701    where
702        F: FnMut(&mut T),
703        T: Clone,
704    {
705        self.send_if_modified(|value| {
706            modify(value);
707            true
708        });
709    }
710
711    /// Modifies the watched value **conditionally**, notifying all receivers
712    /// only if it was modified.
713    ///
714    /// `modify` runs on a clone of the current value and returns `true` if
715    /// it changed it. Only then is the clone published, by a
716    /// compare-and-swap that starts over on the new value when another
717    /// sender published first (so `modify` is `FnMut` and may run more than
718    /// once). When it returns `false` nothing is published, whatever it did
719    /// to its copy: unlike a lock-based channel there is no silent
720    /// modification.
721    ///
722    /// Returns `true` if a new value was published and `false` if `modify`
723    /// returned `false`.
724    ///
725    /// Lock-free: it retries against other senders.
726    ///
727    /// # Panics
728    ///
729    /// Panics if `modify` (or the clone) panics. Nothing is published then.
730    ///
731    /// ```
732    /// use nuclei::sync::watch;
733    ///
734    /// let (tx, mut rx) = watch::channel(1u32);
735    /// let inc_if_odd = |n: &mut u32| {
736    ///     if *n % 2 == 1 {
737    ///         *n += 1;
738    ///         return true;
739    ///     }
740    ///     false
741    /// };
742    /// assert!(tx.send_if_modified(inc_if_odd));
743    /// assert_eq!(*rx.borrow_and_update(), 2);
744    /// assert!(!tx.send_if_modified(inc_if_odd));
745    /// assert!(!rx.has_changed().unwrap());
746    /// ```
747    pub fn send_if_modified<F>(&self, mut modify: F) -> bool
748    where
749        F: FnMut(&mut T) -> bool,
750        T: Clone,
751    {
752        loop {
753            let current = self.shared.value.load();
754            let mut next = T::clone(&current);
755            if !modify(&mut next) {
756                return false;
757            }
758            // The guard in `current` keeps the compared value from being
759            // freed and reused, so the pointer comparison is sound.
760            if self.shared.value.compare_and_swap(&current, next).is_ok() {
761                break;
762            }
763            // Another sender published first: start over from its value.
764        }
765        self.shared.published();
766        true
767    }
768
769    /// Sends a new value, notifying all receivers, and returns a clone of the
770    /// value it replaced.
771    ///
772    /// Also works with no receiver. The old value is returned as a clone
773    /// because receivers may still be reading it; see the
774    /// [module docs](self). The publication is wait-free; the wake of the
775    /// receivers makes the whole call lock-free.
776    ///
777    /// ```
778    /// use nuclei::sync::watch;
779    ///
780    /// let (tx, _rx) = watch::channel(1);
781    /// assert_eq!(tx.send_replace(2), 1);
782    /// assert_eq!(tx.send_replace(3), 2);
783    /// ```
784    pub fn send_replace(&self, value: T) -> T
785    where
786        T: Clone,
787    {
788        let old = self.shared.value.swap(value);
789        // Published before the clone: a clone that panics must not leave a
790        // new value that no receiver hears about.
791        self.shared.published();
792        T::clone(&old)
793    }
794
795    /// Returns a reference to the most recently sent value.
796    ///
797    /// A borrow from the sender is never marked changed. See
798    /// [`Receiver::borrow`] for the advice on holding the reference.
799    ///
800    /// ```
801    /// use nuclei::sync::watch;
802    ///
803    /// let (tx, _) = watch::channel("hello");
804    /// assert_eq!(*tx.borrow(), "hello");
805    /// ```
806    pub fn borrow(&self) -> Ref<'_, T> {
807        Ref {
808            guard: self.shared.value.load(),
809            has_changed: false,
810        }
811    }
812
813    /// Whether the channel is closed for sending: every [`Receiver`] has been
814    /// dropped. [`subscribe`](Self::subscribe) reopens it.
815    ///
816    /// ```
817    /// use nuclei::sync::watch;
818    ///
819    /// let (tx, rx) = watch::channel(());
820    /// assert!(!tx.is_closed());
821    /// drop(rx);
822    /// assert!(tx.is_closed());
823    /// ```
824    pub fn is_closed(&self) -> bool {
825        self.receiver_count() == 0
826    }
827
828    /// Completes when every receiver has been dropped.
829    ///
830    /// Lets the producer stop work nobody wants. If the channel closes
831    /// briefly (the last receiver is dropped and [`subscribe`](Self::subscribe)
832    /// is called again), this may or may not notice.
833    ///
834    /// # Cancel safety
835    ///
836    /// Cancel safe.
837    ///
838    /// ```
839    /// use nuclei::sync::watch;
840    /// use std::future::Future;
841    /// use std::pin::pin;
842    /// use std::task::{Context, Poll, Waker};
843    ///
844    /// let (tx, rx) = watch::channel("hello");
845    /// let mut cx = Context::from_waker(Waker::noop());
846    /// let mut closed = pin!(tx.closed());
847    /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Pending);
848    /// drop(rx);
849    /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Ready(()));
850    /// ```
851    pub async fn closed(&self) {
852        while self.receiver_count() > 0 {
853            // Created before the count is read again, for the reason given at
854            // `changed_impl`: the last receiver's drop wakes it after the
855            // decrement.
856            let notified = self.shared.notify_tx.notified();
857            if self.receiver_count() == 0 {
858                return;
859            }
860            notified.await;
861            // The channel may have been reopened by `subscribe`: look again.
862        }
863    }
864
865    /// Creates a new [`Receiver`] connected to this sender.
866    ///
867    /// The value that is current now counts as seen by the new receiver. It
868    /// works with no other receiver, which reopens the channel.
869    ///
870    /// ```
871    /// use nuclei::sync::watch;
872    ///
873    /// let (tx, _rx) = watch::channel(0u64);
874    /// tx.send(5).unwrap();
875    /// let rx = tx.subscribe();
876    /// assert_eq!(*rx.borrow(), 5);
877    /// assert!(!rx.has_changed().unwrap());
878    /// ```
879    pub fn subscribe(&self) -> Receiver<T> {
880        // The CLOSED bit tracks only whether the senders are gone, so a
881        // reopened channel needs no reset of it.
882        let version = version_of(self.shared.state.load(Ordering::Acquire));
883        Receiver::from_shared(version, Arc::clone(&self.shared))
884    }
885
886    /// How many receivers exist now.
887    ///
888    /// ```
889    /// use nuclei::sync::watch;
890    ///
891    /// let (tx, rx) = watch::channel("hello");
892    /// assert_eq!(tx.receiver_count(), 1);
893    /// let _rx2 = rx.clone();
894    /// assert_eq!(tx.receiver_count(), 2);
895    /// ```
896    pub fn receiver_count(&self) -> usize {
897        // Relaxed: a count; callers that act on it re-check as `closed` does.
898        self.shared.ref_count_rx.load(Ordering::Relaxed)
899    }
900
901    /// How many senders exist now.
902    ///
903    /// ```
904    /// use nuclei::sync::watch;
905    ///
906    /// let (tx, _rx) = watch::channel("hello");
907    /// assert_eq!(tx.sender_count(), 1);
908    /// let tx2 = tx.clone();
909    /// assert_eq!(tx2.sender_count(), 2);
910    /// ```
911    pub fn sender_count(&self) -> usize {
912        // Relaxed: as `receiver_count`.
913        self.shared.ref_count_tx.load(Ordering::Relaxed)
914    }
915
916    /// Whether the two senders belong to the same channel.
917    ///
918    /// ```
919    /// use nuclei::sync::watch;
920    ///
921    /// let (tx, _rx) = watch::channel(true);
922    /// let tx2 = tx.clone();
923    /// assert!(tx.same_channel(&tx2));
924    /// let (tx3, _rx3) = watch::channel(true);
925    /// assert!(!tx3.same_channel(&tx2));
926    /// ```
927    pub fn same_channel(&self, other: &Self) -> bool {
928        Arc::ptr_eq(&self.shared, &other.shared)
929    }
930}
931
932impl<T: Send + Sync + 'static> Clone for Sender<T> {
933    fn clone(&self) -> Self {
934        // Relaxed: a plain counter, and the clone proves a sender exists.
935        self.shared.ref_count_tx.fetch_add(1, Ordering::Relaxed);
936        Self {
937            shared: Arc::clone(&self.shared),
938        }
939    }
940}
941
942impl<T: Send + Sync + 'static + Default> Default for Sender<T> {
943    fn default() -> Self {
944        Self::new(T::default())
945    }
946}
947
948impl<T: Send + Sync + 'static> Drop for Sender<T> {
949    fn drop(&mut self) {
950        // AcqRel: the thread that drops the last sender sees every earlier
951        // sender's sends before it closes the channel.
952        if self.shared.ref_count_tx.fetch_sub(1, Ordering::AcqRel) == 1 {
953            // Release: a receiver that sees CLOSED sees the last version.
954            self.shared.state.fetch_or(CLOSED, Ordering::Release);
955            self.shared.notify_rx.notify_waiters();
956        }
957    }
958}
959
960impl<T: Send + Sync + 'static + fmt::Debug> fmt::Debug for Sender<T> {
961    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
962        f.debug_struct("Sender")
963            .field("shared", &*self.shared)
964            .finish()
965    }
966}
967
968#[cfg(all(test, not(loom)))]
969mod tests {
970    use super::*;
971
972    #[test]
973    fn the_closed_bit_leaves_the_version_alone() {
974        let (tx, rx) = channel(0u8);
975        tx.send(1).unwrap();
976        let before = version_of(tx.shared.state.load(Ordering::Acquire));
977        drop(tx);
978        assert!(rx.is_closed());
979        assert_eq!(version_of(rx.shared.state.load(Ordering::Acquire)), before);
980    }
981
982    #[test]
983    fn the_version_wraps_without_touching_the_closed_bit() {
984        let (tx, rx) = channel(0u8);
985        tx.shared.state.store(u64::MAX - 1, Ordering::SeqCst);
986        tx.send(1).unwrap();
987        let state = tx.shared.state.load(Ordering::SeqCst);
988        assert_eq!(state & CLOSED, 0, "a wrapped version is not a close");
989        assert_eq!(version_of(state), 0);
990        assert!(!rx.is_closed());
991    }
992}