Skip to main content

nuclei/sync/mpsc/
unbounded.rs

1//! The unbounded channel: [`unbounded_channel`], [`UnboundedSender`],
2//! [`WeakUnboundedSender`] and [`UnboundedReceiver`].
3//!
4//! The channel's admission control is one word: the number of values in flight
5//! above a closed bit. A send adds one with a compare-and-swap that refuses
6//! once the closed bit is up, the receiver subtracts one per value it takes,
7//! and the receiver closing sets the bit. The word is idle when no value is
8//! queued or on its way, which is what a closed receiver waits for before it
9//! reports the end.
10
11use core::fmt;
12use core::future::poll_fn;
13use core::task::{Context, Poll};
14
15use super::chan::{Chan, Limit};
16use super::error::{SendError, TryRecvError};
17use super::queue;
18use crate::sync::internal::{self, Arc, AtomicUsize, Ordering};
19
20/// Set when the receiver closed; the count of values in flight sits above it.
21const CLOSED: usize = 1;
22/// One value, in the units of the word.
23const ONE: usize = 2;
24
25/// The unbounded flavor's limit: values in flight, and the closed bit.
26pub(super) struct Unbounded(AtomicUsize);
27
28impl Unbounded {
29    /// Admits one more value unless the channel is closed. Wait-free: one
30    /// fetch-add, and on a closed channel one fetch-sub that takes it back.
31    /// The count was up for that instant, so a receiver waiting for its closed
32    /// channel to go idle may have seen it: the caller wakes it after a refusal
33    /// ([`Chan::wake_if_finished`](super::chan::Chan::wake_if_finished)).
34    #[inline]
35    fn admit(&self) -> bool {
36        // Cannot overflow into the closed bit: it would take 2^62 values in
37        // flight at once, and each one occupies at least a word of the message
38        // queue's memory (a refused one for an instant only).
39        let before = self.0.fetch_add(ONE, Ordering::AcqRel);
40        if before & CLOSED == 0 {
41            return true;
42        }
43        self.0.fetch_sub(ONE, Ordering::AcqRel);
44        false
45    }
46}
47
48impl Limit for Unbounded {
49    type Queue<T> = queue::Radix<T>;
50
51    fn queue<T>(&self) -> queue::Radix<T> {
52        queue::Radix::new()
53    }
54
55    #[inline]
56    fn is_idle(&self) -> bool {
57        self.0.load(Ordering::Acquire) >> 1 == 0
58    }
59
60    #[inline]
61    fn release(&self, n: usize) {
62        let before = self.0.fetch_sub(n * ONE, Ordering::AcqRel);
63        debug_assert!(before >> 1 >= n, "released more values than were admitted");
64    }
65
66    fn close(&self) {
67        self.0.fetch_or(CLOSED, Ordering::AcqRel);
68    }
69
70    #[inline]
71    fn is_closed(&self) -> bool {
72        self.0.load(Ordering::Acquire) & CLOSED != 0
73    }
74}
75
76/// Creates an unbounded channel for communicating between tasks without
77/// backpressure.
78///
79/// A send never waits and never fails for lack of room, so
80/// [`UnboundedSender::send`] is an ordinary function, usable from synchronous
81/// and asynchronous code alike. The queue grows with the values sent faster
82/// than they are received, so memory is the only limit; use
83/// [`channel`](super::channel) where a producer can outrun the receiver.
84///
85/// Everything sent on an [`UnboundedSender`] comes out of the
86/// [`UnboundedReceiver`], in the order it was sent (see
87/// [Ordering](super#ordering)). The sender can be cloned; only one receiver
88/// exists.
89///
90/// ```
91/// use nuclei::sync::mpsc;
92///
93/// let (tx, mut rx) = mpsc::unbounded_channel();
94/// let producer = std::thread::spawn(move || {
95///     for i in 0..10 {
96///         tx.send(i).expect("the receiver is still there");
97///     }
98/// });
99/// for i in 0..10 {
100///     assert_eq!(rx.blocking_recv(), Some(i));
101/// }
102/// assert_eq!(rx.blocking_recv(), None);
103/// producer.join().unwrap();
104/// ```
105pub fn unbounded_channel<T>() -> (UnboundedSender<T>, UnboundedReceiver<T>) {
106    let chan = Arc::new(Chan::new(Unbounded(AtomicUsize::new(0))));
107    let tx = UnboundedSender {
108        chan: Arc::clone(&chan),
109    };
110    (tx, UnboundedReceiver { chan })
111}
112
113/// Sends values to the associated [`UnboundedReceiver`].
114///
115/// Created by [`unbounded_channel`]. Cloning it is a reference-count
116/// increment.
117///
118/// # Progress
119///
120/// Wait-free (a bounded number of the caller's own atomic steps):
121/// [`is_closed`](Self::is_closed), [`same_channel`](Self::same_channel),
122/// [`strong_count`](Self::strong_count), [`weak_count`](Self::weak_count),
123/// [`downgrade`](Self::downgrade), `clone` and `drop`. The drop of the last
124/// sender ends with a wake of the receiver's waker cell, which is two atomic
125/// steps; what the waker then does belongs to the executor.
126///
127/// Lock-free, not wait-free: [`send`](Self::send). It admits the value with a
128/// compare-and-swap that retries when another sender or the receiver changed
129/// the count first, and then pushes onto the message queue, which retries when
130/// it loses a slot to another sender and allocates a segment when the last one
131/// is full. Some thread's call completes whenever any retries.
132/// [`closed`](Self::closed) is lock-free: a poll may queue a waiter.
133pub struct UnboundedSender<T> {
134    chan: Arc<Chan<T, Unbounded>>,
135}
136
137/// A sender that does not keep the channel open.
138///
139/// When every [`UnboundedSender`] is dropped and only `WeakUnboundedSender`s
140/// remain, the channel is closed for the receiver. [`upgrade`](Self::upgrade)
141/// turns it into an [`UnboundedSender`] while one exists.
142///
143/// ```
144/// use nuclei::sync::mpsc;
145///
146/// let (tx, _rx) = mpsc::unbounded_channel::<i32>();
147/// let weak = tx.downgrade();
148/// assert!(weak.upgrade().is_some());
149/// drop(tx);
150/// assert!(weak.clone().upgrade().is_none());
151/// ```
152///
153/// # Progress
154///
155/// `clone`, `drop`, [`strong_count`](Self::strong_count) and
156/// [`weak_count`](Self::weak_count) are wait-free. [`upgrade`](Self::upgrade)
157/// is lock-free, not wait-free: it is a compare-and-swap on the sender count
158/// that retries when a sender was cloned or dropped meanwhile.
159pub struct WeakUnboundedSender<T> {
160    chan: Arc<Chan<T, Unbounded>>,
161}
162
163/// Receives values from the associated [`UnboundedSender`]s.
164///
165/// Created by [`unbounded_channel`]. There is exactly one receiver.
166///
167/// # Progress
168///
169/// Wait-free: [`is_closed`](Self::is_closed), [`is_empty`](Self::is_empty),
170/// [`len`](Self::len), [`sender_strong_count`](Self::sender_strong_count) and
171/// [`sender_weak_count`](Self::sender_weak_count): each is a load.
172///
173/// Lock-free: [`recv`](Self::recv), [`recv_many`](Self::recv_many),
174/// [`try_recv`](Self::try_recv) and the two `poll_` forms. Registering the
175/// waker is wait-free (the cell runs two read-modify-writes and no loop).
176/// Taking a value off the message queue is a compare-and-swap no other thread
177/// contends for, and never waits for a sender: a value whose send claimed its
178/// place and has not written it yet is not there, and its sender wakes the
179/// receiver once it is (see the [Progress](super#progress) notes of the
180/// module). [`close`](Self::close) is lock-free: one `fetch_or` on the
181/// count, then the set of the event that `closed` waits on, which takes that
182/// event's drain role. The drop is the same as a receive per value left, since
183/// it drops every value still queued, and so takes time proportional to them.
184///
185/// `blocking_recv` and `blocking_recv_many` park the calling thread until a
186/// value arrives.
187pub struct UnboundedReceiver<T> {
188    chan: Arc<Chan<T, Unbounded>>,
189}
190
191impl<T> UnboundedSender<T> {
192    /// Sends a value, without waiting.
193    ///
194    /// A successful send means the other end had not hung up when the value
195    /// was published. `Ok` does not mean the value will be received: the
196    /// receiver can hang up right after.
197    ///
198    /// # Errors
199    ///
200    /// If the receiving half is closed, by [`UnboundedReceiver::close`] or by
201    /// being dropped, the function returns an error that holds the value.
202    ///
203    /// ```
204    /// use nuclei::sync::mpsc;
205    ///
206    /// let (tx, mut rx) = mpsc::unbounded_channel();
207    /// tx.send("first").unwrap();
208    /// assert_eq!(rx.try_recv(), Ok("first"));
209    /// drop(rx);
210    /// assert_eq!(tx.send("second").unwrap_err().0, "second");
211    /// ```
212    pub fn send(&self, message: T) -> Result<(), SendError<T>> {
213        if !self.chan.limit.admit() {
214            // The refused admission was counted for an instant (see `admit`).
215            self.chan.wake_if_finished();
216            return Err(SendError(message));
217        }
218        self.chan.send(message);
219        Ok(())
220    }
221
222    /// Completes when the receiver has been closed or dropped.
223    ///
224    /// This lets a producer learn that nobody wants its values any more and
225    /// stop work early.
226    ///
227    /// # Cancel safety
228    ///
229    /// Cancel safe. Once the channel is closed it stays closed, and every later
230    /// call completes at once.
231    ///
232    /// ```
233    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
234    /// use nuclei::sync::mpsc;
235    ///
236    /// let (tx, rx) = mpsc::unbounded_channel::<()>();
237    /// let mut cx = Context::from_waker(Waker::noop());
238    /// let mut closed = pin!(tx.closed());
239    /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Pending);
240    /// drop(rx);
241    /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Ready(()));
242    /// ```
243    pub async fn closed(&self) {
244        self.chan.closed().await;
245    }
246
247    /// Whether the channel is closed: the receiver was closed or dropped.
248    ///
249    /// ```
250    /// use nuclei::sync::mpsc;
251    ///
252    /// let (tx, rx) = mpsc::unbounded_channel::<()>();
253    /// assert!(!tx.is_closed());
254    /// drop(rx);
255    /// assert!(tx.is_closed());
256    /// ```
257    pub fn is_closed(&self) -> bool {
258        self.chan.is_closed()
259    }
260
261    /// Whether two senders belong to the same channel.
262    ///
263    /// ```
264    /// use nuclei::sync::mpsc;
265    ///
266    /// let (tx, _rx) = mpsc::unbounded_channel::<()>();
267    /// let tx2 = tx.clone();
268    /// assert!(tx.same_channel(&tx2));
269    ///
270    /// let (tx3, _rx3) = mpsc::unbounded_channel::<()>();
271    /// assert!(!tx3.same_channel(&tx2));
272    /// ```
273    pub fn same_channel(&self, other: &Self) -> bool {
274        Arc::ptr_eq(&self.chan, &other.chan)
275    }
276
277    /// Converts the sender into a [`WeakUnboundedSender`], which does not keep
278    /// the channel open. The sender itself stays.
279    #[must_use = "Downgrade creates a WeakUnboundedSender without destroying the original non-weak sender."]
280    pub fn downgrade(&self) -> WeakUnboundedSender<T> {
281        self.chan.add_weak();
282        WeakUnboundedSender {
283            chan: Arc::clone(&self.chan),
284        }
285    }
286
287    /// How many [`UnboundedSender`] handles exist.
288    pub fn strong_count(&self) -> usize {
289        self.chan.strong_count()
290    }
291
292    /// How many [`WeakUnboundedSender`] handles exist.
293    pub fn weak_count(&self) -> usize {
294        self.chan.weak_count()
295    }
296}
297
298impl<T> Clone for UnboundedSender<T> {
299    fn clone(&self) -> Self {
300        self.chan.add_sender();
301        UnboundedSender {
302            chan: Arc::clone(&self.chan),
303        }
304    }
305}
306
307impl<T> Drop for UnboundedSender<T> {
308    fn drop(&mut self) {
309        self.chan.drop_sender();
310    }
311}
312
313impl<T> fmt::Debug for UnboundedSender<T> {
314    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315        f.debug_struct("UnboundedSender")
316            .field("closed", &self.is_closed())
317            .finish()
318    }
319}
320
321impl<T> WeakUnboundedSender<T> {
322    /// Tries to turn the weak sender into an [`UnboundedSender`].
323    ///
324    /// Returns `Some` while at least one [`UnboundedSender`] is alive, and
325    /// `None` once the last is gone.
326    pub fn upgrade(&self) -> Option<UnboundedSender<T>> {
327        self.chan.try_add_sender().then(|| UnboundedSender {
328            chan: Arc::clone(&self.chan),
329        })
330    }
331
332    /// How many [`UnboundedSender`] handles exist.
333    pub fn strong_count(&self) -> usize {
334        self.chan.strong_count()
335    }
336
337    /// How many [`WeakUnboundedSender`] handles exist.
338    pub fn weak_count(&self) -> usize {
339        self.chan.weak_count()
340    }
341}
342
343impl<T> Clone for WeakUnboundedSender<T> {
344    fn clone(&self) -> Self {
345        self.chan.add_weak();
346        WeakUnboundedSender {
347            chan: Arc::clone(&self.chan),
348        }
349    }
350}
351
352impl<T> Drop for WeakUnboundedSender<T> {
353    fn drop(&mut self) {
354        self.chan.drop_weak();
355    }
356}
357
358impl<T> fmt::Debug for WeakUnboundedSender<T> {
359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360        f.debug_struct("WeakUnboundedSender").finish()
361    }
362}
363
364impl<T> UnboundedReceiver<T> {
365    /// Receives the next value.
366    ///
367    /// Returns `None` once the channel is closed and no buffered value is
368    /// left, which means no value can ever be received again. The channel is
369    /// closed when every sender has been dropped, or when
370    /// [`close`](Self::close) is called. If the channel is empty and open, it
371    /// waits for a send or a close.
372    ///
373    /// # Cancel safety
374    ///
375    /// Cancel safe. If the future is dropped (for instance when another branch
376    /// of a `select` wins), no value was taken from the channel.
377    ///
378    /// ```
379    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
380    /// # fn now<F: Future>(f: F) -> F::Output {
381    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
382    /// #         Poll::Ready(out) => out,
383    /// #         Poll::Pending => panic!("not ready"),
384    /// #     }
385    /// # }
386    /// use nuclei::sync::mpsc;
387    ///
388    /// let (tx, mut rx) = mpsc::unbounded_channel();
389    /// tx.send("hello").unwrap();
390    /// tx.send("world").unwrap();
391    /// drop(tx);
392    /// assert_eq!(now(rx.recv()), Some("hello"));
393    /// assert_eq!(now(rx.recv()), Some("world"));
394    /// assert_eq!(now(rx.recv()), None);
395    /// ```
396    pub async fn recv(&mut self) -> Option<T> {
397        poll_fn(|cx| self.poll_recv(cx)).await
398    }
399
400    /// Receives the next values and appends them to `buffer`, taking at most
401    /// `limit` of them in one call.
402    ///
403    /// Returns how many values it added. A `limit` of zero returns `0` at
404    /// once. Otherwise it waits like [`recv`](Self::recv) until at least one
405    /// value is there, then takes everything that is ready up to `limit`
406    /// without waiting again, and returns `0` only when the channel is closed
407    /// and empty. The capacity of `buffer` grows as needed.
408    ///
409    /// # Cancel safety
410    ///
411    /// Cancel safe, as [`recv`](Self::recv): a dropped future took nothing.
412    ///
413    /// ```
414    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
415    /// # fn now<F: Future>(f: F) -> F::Output {
416    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
417    /// #         Poll::Ready(out) => out,
418    /// #         Poll::Pending => panic!("not ready"),
419    /// #     }
420    /// # }
421    /// use nuclei::sync::mpsc;
422    ///
423    /// let (tx, mut rx) = mpsc::unbounded_channel();
424    /// for word in ["first", "second", "third"] {
425    ///     tx.send(word).unwrap();
426    /// }
427    /// let mut buffer = Vec::new();
428    /// assert_eq!(now(rx.recv_many(&mut buffer, 2)), 2);
429    /// assert_eq!(buffer, ["first", "second"]);
430    /// assert_eq!(now(rx.recv_many(&mut buffer, 2)), 1);
431    /// drop(tx);
432    /// assert_eq!(now(rx.recv_many(&mut buffer, 2)), 0);
433    /// ```
434    pub async fn recv_many(&mut self, buffer: &mut Vec<T>, limit: usize) -> usize {
435        poll_fn(|cx| self.poll_recv_many(cx, buffer, limit)).await
436    }
437
438    /// Tries to receive the next value without waiting.
439    ///
440    /// # Errors
441    ///
442    /// [`TryRecvError::Empty`] if the channel is empty but a sender still
443    /// exists, so a value may yet come. [`TryRecvError::Disconnected`] if it
444    /// is empty and nothing can send: every sender is gone, or the channel was
445    /// closed.
446    ///
447    /// A value whose send is still in progress on another thread is not in the
448    /// channel yet, nor are the values sent after it, which come out behind
449    /// it. This call does not wait for them: the sender wakes the receiver
450    /// once its value is in.
451    ///
452    /// ```
453    /// use nuclei::sync::mpsc::{self, error::TryRecvError};
454    ///
455    /// let (tx, mut rx) = mpsc::unbounded_channel();
456    /// tx.send("hello").unwrap();
457    /// assert_eq!(rx.try_recv(), Ok("hello"));
458    /// assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
459    /// drop(tx);
460    /// assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
461    /// ```
462    pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
463        // SAFETY: `&mut self` of the channel's one receiver.
464        unsafe { self.chan.try_recv() }
465    }
466
467    /// Receives the next value from a thread that may block.
468    ///
469    /// Like [`recv`](Self::recv), but it parks the calling thread while the
470    /// channel is empty and open. On a nuclei shard (inside one of its tasks) it does not park the thread: it runs a nested `block_on`, so the shard keeps running its other tasks meanwhile. Inside another runtime's task it
471    /// blocks that task's thread.
472    ///
473    /// # Panics
474    ///
475    /// On `wasm32`, where no other thread can send, when the channel is empty
476    /// and open: the call could never end.
477    ///
478    /// ```
479    /// use nuclei::sync::mpsc;
480    ///
481    /// let (tx, mut rx) = mpsc::unbounded_channel::<u8>();
482    /// let receiver = std::thread::spawn(move || {
483    ///     assert_eq!(rx.blocking_recv(), Some(10));
484    ///     assert_eq!(rx.blocking_recv(), None);
485    /// });
486    /// tx.send(10).unwrap();
487    /// drop(tx);
488    /// receiver.join().unwrap();
489    /// ```
490    pub fn blocking_recv(&mut self) -> Option<T> {
491        internal::blocking(self.recv())
492    }
493
494    /// [`recv_many`](Self::recv_many) for a thread that may block; see
495    /// [`blocking_recv`](Self::blocking_recv).
496    ///
497    /// # Panics
498    ///
499    /// As for [`blocking_recv`](Self::blocking_recv).
500    pub fn blocking_recv_many(&mut self, buffer: &mut Vec<T>, limit: usize) -> usize {
501        internal::blocking(self.recv_many(buffer, limit))
502    }
503
504    /// Closes the receiving half without dropping it.
505    ///
506    /// No further value can be sent: a send fails and returns its value. The
507    /// values already buffered stay receivable, so a clean shutdown closes,
508    /// then calls [`recv`](Self::recv) until it returns `None`. A send that
509    /// was already under way when the channel closed still completes and is
510    /// received first.
511    ///
512    /// ```
513    /// use nuclei::sync::mpsc;
514    ///
515    /// let (tx, mut rx) = mpsc::unbounded_channel();
516    /// tx.send(1).unwrap();
517    /// rx.close();
518    /// assert_eq!(tx.send(2).unwrap_err().0, 2);
519    /// assert_eq!(rx.try_recv(), Ok(1), "the buffered value is still there");
520    /// ```
521    pub fn close(&mut self) {
522        self.chan.close_rx();
523    }
524
525    /// Whether the channel is closed: [`close`](Self::close) was called, or
526    /// every sender is gone. Buffered values may still be received.
527    ///
528    /// ```
529    /// use nuclei::sync::mpsc;
530    ///
531    /// let (tx, mut rx) = mpsc::unbounded_channel::<()>();
532    /// assert!(!rx.is_closed());
533    /// rx.close();
534    /// assert!(rx.is_closed());
535    /// drop(tx);
536    /// ```
537    pub fn is_closed(&self) -> bool {
538        self.chan.rx_is_closed()
539    }
540
541    /// Whether the channel holds no value.
542    ///
543    /// ```
544    /// use nuclei::sync::mpsc;
545    ///
546    /// let (tx, rx) = mpsc::unbounded_channel();
547    /// assert!(rx.is_empty());
548    /// tx.send(()).unwrap();
549    /// assert!(!rx.is_empty());
550    /// ```
551    pub fn is_empty(&self) -> bool {
552        self.chan.len() == 0
553    }
554
555    /// How many values the channel holds.
556    ///
557    /// A snapshot: it is exact while no other thread is sending, and while one
558    /// is it may be off by the values being sent at that moment.
559    ///
560    /// ```
561    /// use nuclei::sync::mpsc;
562    ///
563    /// let (tx, rx) = mpsc::unbounded_channel();
564    /// assert_eq!(rx.len(), 0);
565    /// tx.send(()).unwrap();
566    /// assert_eq!(rx.len(), 1);
567    /// ```
568    pub fn len(&self) -> usize {
569        self.chan.len()
570    }
571
572    /// Polls to receive the next value.
573    ///
574    /// Returns [`Poll::Pending`] if no value is available and the channel is
575    /// open; [`Poll::Ready`]`(Some(value))` if one is; and
576    /// [`Poll::Ready`]`(None)` if the channel is closed and every value sent
577    /// before it closed was received.
578    ///
579    /// On `Pending`, the waker of `cx` is woken when a value arrives or the
580    /// channel closes. Only the waker of the most recent call to `poll_recv`
581    /// or [`poll_recv_many`](Self::poll_recv_many) is kept.
582    pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
583        // SAFETY: `&mut self` of the channel's one receiver.
584        unsafe { self.chan.poll_recv(cx) }
585    }
586
587    /// Polls to receive several values into `buffer`, at most `limit`.
588    ///
589    /// Returns [`Poll::Pending`] if no value is available and the channel is
590    /// open; [`Poll::Ready`]`(count)` with the number of values added, which
591    /// is at least one unless `limit` is zero or the channel is closed and
592    /// empty. It takes everything that is ready, up to `limit`, in one call.
593    /// The waker of `cx` is handled as for [`poll_recv`](Self::poll_recv).
594    pub fn poll_recv_many(
595        &mut self,
596        cx: &mut Context<'_>,
597        buffer: &mut Vec<T>,
598        limit: usize,
599    ) -> Poll<usize> {
600        // SAFETY: `&mut self` of the channel's one receiver.
601        unsafe { self.chan.poll_recv_many(cx, buffer, limit) }
602    }
603
604    /// How many [`UnboundedSender`] handles exist.
605    pub fn sender_strong_count(&self) -> usize {
606        self.chan.strong_count()
607    }
608
609    /// How many [`WeakUnboundedSender`] handles exist.
610    pub fn sender_weak_count(&self) -> usize {
611        self.chan.weak_count()
612    }
613}
614
615impl<T> Drop for UnboundedReceiver<T> {
616    fn drop(&mut self) {
617        // SAFETY: the channel's one receiver, dropping.
618        unsafe { self.chan.drop_rx() };
619    }
620}
621
622impl<T> fmt::Debug for UnboundedReceiver<T> {
623    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
624        f.debug_struct("UnboundedReceiver")
625            .field("closed", &self.is_closed())
626            .field("len", &self.len())
627            .finish()
628    }
629}
630
631#[cfg(all(test, not(loom)))]
632mod tests {
633    use super::*;
634    use crate::sync::test_support::Polled;
635
636    #[test]
637    fn the_word_counts_values_in_flight_above_the_closed_bit() {
638        let limit = Unbounded(AtomicUsize::new(0));
639        assert!(limit.is_idle() && !limit.is_closed());
640        assert!(limit.admit() && limit.admit());
641        assert!(!limit.is_idle());
642        limit.release(1);
643        assert!(!limit.is_idle());
644        limit.close();
645        limit.close();
646        assert!(limit.is_closed());
647        assert!(!limit.admit(), "a closed channel admits nothing");
648        limit.release(1);
649        assert!(limit.is_idle() && limit.is_closed());
650    }
651
652    #[test]
653    fn a_receiver_waiting_on_a_closed_channel_ends_when_the_last_value_is_taken() {
654        let (tx, mut rx) = unbounded_channel::<u8>();
655        tx.send(1).unwrap();
656        rx.close();
657        assert_eq!(rx.try_recv(), Ok(1));
658        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
659        let mut recv = Polled::new(rx.recv());
660        assert_eq!(recv.ready(), None);
661    }
662}