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}