Skip to main content

nuclei/sync/mpsc/
bounded.rs

1//! The bounded channel: [`channel`], its [`Sender`] and its [`WeakSender`].
2//!
3//! The channel's admission control is a [`FairSemaphore`] of `buffer`
4//! permits. A send takes one permit (a reservation is exactly that), the
5//! receiver gives one back per value it takes, and a permit dropped unused
6//! goes back too. So the permits free, plus the ones set aside for a waiting
7//! reservation, plus the values queued, plus the reservations held, are
8//! always `buffer`, and the queue can never hold more than `buffer` values.
9//!
10//! The semaphore serves reservations strictly in the order they began to
11//! wait, as the established API does: a `try_` attempt or a new reservation
12//! never takes a slot while an older one waits, and a reservation for many
13//! slots keeps the ones set aside for it while it waits for the rest. The
14//! receiver closing closes the semaphore: waiting senders end at once, what
15//! was set aside for them comes back, and every later reservation fails.
16
17#![allow(unsafe_code)]
18
19use core::fmt;
20use core::future::Future;
21use core::marker::PhantomPinned;
22use core::pin::Pin;
23use core::task::{Context, Poll};
24
25use super::chan::{Chan, Limit};
26use super::error::{SendError, SendTimeoutError, TrySendError};
27use super::permit::{OwnedPermit, Permit, PermitIterator};
28use super::queue;
29use super::receiver::Receiver;
30use crate::sync::fair_semaphore::{FairSemaphore, FairWait};
31use crate::sync::internal::{self, Arc};
32use crate::sync::raw_semaphore::observed_closed;
33
34/// The bounded flavor's limit: `bound` permits.
35pub(super) struct Bounded {
36    pub(super) sem: FairSemaphore,
37    pub(super) bound: usize,
38}
39
40impl Limit for Bounded {
41    type Queue<T> = queue::Bounded<T>;
42
43    fn queue<T>(&self) -> queue::Bounded<T> {
44        queue::Bounded::with_capacity(self.bound)
45    }
46
47    #[inline]
48    fn is_idle(&self) -> bool {
49        self.sem.available() == self.bound
50    }
51
52    #[inline]
53    fn release(&self, n: usize) {
54        self.sem.release(n);
55    }
56
57    fn close(&self) {
58        self.sem.close();
59    }
60
61    #[inline]
62    fn is_closed(&self) -> bool {
63        self.sem.is_closed()
64    }
65}
66
67/// Creates a bounded channel for communicating between tasks with
68/// backpressure.
69///
70/// The channel buffers up to `buffer` messages. Once the buffer is full, a
71/// send waits until a message is received. The buffer must hold at least one
72/// message.
73///
74/// Everything sent on a [`Sender`] comes out of the [`Receiver`], in the order
75/// it was sent (see [Ordering](super#ordering)). The [`Sender`] can be cloned
76/// to send to the same channel from many places; only one [`Receiver`] exists.
77///
78/// If the [`Receiver`] is closed or dropped, a send returns a
79/// [`SendError`] with the value. When every [`Sender`] is dropped, `recv`
80/// returns `None` once the buffered messages are received.
81///
82/// # Panics
83///
84/// Panics if `buffer` is 0, or larger than
85/// [`Semaphore::MAX_PERMITS`](crate::sync::Semaphore::MAX_PERMITS).
86///
87/// ```
88/// use nuclei::sync::mpsc;
89///
90/// let (tx, mut rx) = mpsc::channel(4);
91/// let producer = std::thread::spawn(move || {
92///     for i in 0..10 {
93///         tx.blocking_send(i).expect("the receiver is still there");
94///     }
95/// });
96/// for i in 0..10 {
97///     assert_eq!(rx.blocking_recv(), Some(i));
98/// }
99/// assert_eq!(rx.blocking_recv(), None);
100/// producer.join().unwrap();
101/// ```
102#[track_caller]
103pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
104    assert!(buffer > 0, "mpsc bounded channel requires buffer > 0");
105    let chan = Arc::new(Chan::new(Bounded {
106        sem: FairSemaphore::new(buffer),
107        bound: buffer,
108    }));
109    let tx = Sender {
110        chan: Arc::clone(&chan),
111    };
112    (tx, Receiver::new(chan))
113}
114
115/// Sends values to the associated [`Receiver`].
116///
117/// Created by [`channel`]. Cloning it is a reference-count increment.
118///
119/// # Progress
120///
121/// Wait-free (a bounded number of the caller's own atomic steps whatever other
122/// threads do): [`is_closed`](Self::is_closed), [`capacity`](Self::capacity),
123/// [`max_capacity`](Self::max_capacity), [`same_channel`](Self::same_channel),
124/// [`strong_count`](Self::strong_count), [`weak_count`](Self::weak_count),
125/// [`downgrade`](Self::downgrade), `clone` and `drop`. The drop of the last
126/// sender ends with a wake of the receiver's waker cell, which is two atomic
127/// steps; what the waker then does belongs to the executor.
128///
129/// Lock-free, not wait-free: [`try_send`](Self::try_send), the `try_reserve`
130/// family, and every poll of [`send`](Self::send) and the `reserve` family.
131/// A permit is taken with a compare-and-swap that retries when another thread
132/// changed the semaphore first; a wait that has to queue pushes a node on the
133/// semaphore's lock-free arrival stack and may serve the queue (one pass, plus
134/// one for each operation of another thread that lands meanwhile); and the
135/// push of a value onto the message queue retries when it loses a slot to
136/// another sender and allocates a segment when the last one is full. Some
137/// thread's call completes whenever any retries. [`closed`](Self::closed) is
138/// lock-free for the same reason.
139///
140/// A waiting reservation is granted by whichever thread serves the queue once
141/// its slots are free (the receiver taking a value, a permit dropped), so a
142/// thread the scheduler stops while it serves the queue delays that grant
143/// until it runs again; for that moment a `try_` attempt fails as well, even
144/// if the last waiting reservation has just left. No call waits for it.
145///
146/// `blocking_send` parks the calling thread until there is room.
147pub struct Sender<T> {
148    pub(super) chan: Arc<Chan<T, Bounded>>,
149}
150
151/// A sender that does not keep the channel open.
152///
153/// When every [`Sender`] is dropped and only `WeakSender`s remain, the channel
154/// is closed for the receiver. A `WeakSender` sends nothing itself:
155/// [`upgrade`](Self::upgrade) turns it into a [`Sender`] while one exists.
156///
157/// ```
158/// use nuclei::sync::mpsc;
159///
160/// let (tx, _rx) = mpsc::channel::<i32>(15);
161/// let weak = tx.downgrade();
162/// assert!(weak.upgrade().is_some());
163/// drop(tx);
164/// assert!(weak.clone().upgrade().is_none());
165/// ```
166///
167/// # Progress
168///
169/// `clone`, `drop`, [`strong_count`](Self::strong_count) and
170/// [`weak_count`](Self::weak_count) are wait-free. [`upgrade`](Self::upgrade)
171/// is lock-free, not wait-free: it is a compare-and-swap on the sender count
172/// that retries when a sender was cloned or dropped meanwhile.
173pub struct WeakSender<T> {
174    chan: Arc<Chan<T, Bounded>>,
175}
176
177impl<T> Sender<T> {
178    /// Sends a value, waiting until there is capacity.
179    ///
180    /// A successful send means the other end had not hung up when the value
181    /// was published. `Ok` does not mean the value will be received: the
182    /// receiver can hang up right after.
183    ///
184    /// # Errors
185    ///
186    /// If the receiving half is closed, by [`Receiver::close`] or by being
187    /// dropped, the function returns an error that holds the value passed to
188    /// `send`.
189    ///
190    /// # Cancel safety
191    ///
192    /// If the returned future is dropped before it completes, the message was
193    /// not sent, and the value is dropped. To keep the value, reserve capacity
194    /// with [`reserve`](Self::reserve) and send through the [`Permit`].
195    ///
196    /// Waiting sends and reservations are served in the order they began to
197    /// wait. Dropping the future gives up its place, and a slot it was handed
198    /// meanwhile goes on to the next one.
199    ///
200    /// ```
201    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
202    /// # fn now<F: Future>(f: F) -> F::Output {
203    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
204    /// #         Poll::Ready(out) => out,
205    /// #         Poll::Pending => panic!("not ready"),
206    /// #     }
207    /// # }
208    /// use nuclei::sync::mpsc;
209    ///
210    /// let (tx, mut rx) = mpsc::channel(1);
211    /// now(tx.send(1)).unwrap();
212    /// assert_eq!(rx.try_recv(), Ok(1));
213    ///
214    /// drop(rx);
215    /// let err = now(tx.send(2)).unwrap_err();
216    /// assert_eq!(err.0, 2);
217    /// ```
218    pub fn send(&self, value: T) -> impl Future<Output = Result<(), SendError<T>>> + '_ {
219        Sending {
220            chan: &self.chan,
221            wait: FairWait::new(),
222            value: Some(value),
223            _pinned: PhantomPinned,
224        }
225    }
226
227    /// Sends a value, waiting for room at most `timeout`.
228    ///
229    /// As [`send`](Self::send), with a deadline: the value comes back in
230    /// [`SendTimeoutError::Timeout`] if the channel stayed full until then,
231    /// and in [`SendTimeoutError::Closed`] if the receiver is gone. The wait
232    /// is on nuclei's timers: on a thread that runs no nuclei shard, the
233    /// default runtime fires it.
234    ///
235    /// # Cancel safety
236    ///
237    /// As [`send`](Self::send): a dropped future sent nothing, and drops its
238    /// value.
239    ///
240    /// ```
241    /// use std::time::Duration;
242    /// use nuclei::sync::mpsc::{self, error::SendTimeoutError};
243    ///
244    /// nuclei::runtime::block_on(async {
245    ///     let (tx, _rx) = mpsc::channel(1);
246    ///     tx.send_timeout(1, Duration::from_millis(10)).await.unwrap();
247    ///     let full = tx.send_timeout(2, Duration::from_millis(10)).await;
248    ///     assert!(matches!(full, Err(SendTimeoutError::Timeout(2))));
249    /// });
250    /// ```
251    pub async fn send_timeout(
252        &self,
253        value: T,
254        timeout: std::time::Duration,
255    ) -> Result<(), SendTimeoutError<T>> {
256        match crate::time::timeout(timeout, self.reserve()).await {
257            Ok(Ok(permit)) => {
258                permit.send(value);
259                Ok(())
260            }
261            Ok(Err(_)) => Err(SendTimeoutError::Closed(value)),
262            Err(_) => Err(SendTimeoutError::Timeout(value)),
263        }
264    }
265
266    /// Completes when the receiver has been closed or dropped.
267    ///
268    /// This lets a producer learn that nobody wants its values any more and
269    /// stop work early.
270    ///
271    /// # Cancel safety
272    ///
273    /// Cancel safe. Once the channel is closed it stays closed, and every later
274    /// call completes at once.
275    ///
276    /// ```
277    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
278    /// use nuclei::sync::mpsc;
279    ///
280    /// let (tx, rx) = mpsc::channel::<()>(1);
281    /// let mut cx = Context::from_waker(Waker::noop());
282    /// let mut closed = pin!(tx.closed());
283    /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Pending);
284    /// drop(rx);
285    /// assert_eq!(closed.as_mut().poll(&mut cx), Poll::Ready(()));
286    /// ```
287    pub async fn closed(&self) {
288        self.chan.closed().await;
289    }
290
291    /// Sends a value at once, or says why it cannot be sent.
292    ///
293    /// Unlike [`send`](Self::send) it never waits: a full buffer is an error.
294    /// It never takes a slot ahead of a send or reservation that is waiting.
295    ///
296    /// # Errors
297    ///
298    /// [`TrySendError::Full`] if no slot is free or a send or reservation is
299    /// waiting, [`TrySendError::Closed`] if the receiver closed or was
300    /// dropped. Both hold the value back.
301    ///
302    /// ```
303    /// use nuclei::sync::mpsc::{self, error::TrySendError};
304    ///
305    /// let (tx, mut rx) = mpsc::channel(1);
306    /// tx.try_send("first").unwrap();
307    /// assert!(matches!(tx.try_send("second"), Err(TrySendError::Full("second"))));
308    /// assert_eq!(rx.try_recv(), Ok("first"));
309    /// ```
310    pub fn try_send(&self, message: T) -> Result<(), TrySendError<T>> {
311        match try_reserve_inner(&self.chan, 1) {
312            Ok(()) => {
313                self.chan.send(message);
314                Ok(())
315            }
316            Err(refused) => Err(refused.with_value(message)),
317        }
318    }
319
320    /// Sends a value from a thread that may block.
321    ///
322    /// It parks the calling thread until there is room. 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
323    /// runtime's task it blocks that task's thread. It works whether or not
324    /// the receiver uses [`Receiver::blocking_recv`].
325    ///
326    /// # Panics
327    ///
328    /// On `wasm32`, where no other thread can make room, when the channel is
329    /// full: the call could never end.
330    ///
331    /// ```
332    /// use nuclei::sync::mpsc;
333    ///
334    /// let (tx, mut rx) = mpsc::channel::<u8>(1);
335    /// let sender = std::thread::spawn(move || tx.blocking_send(10).unwrap());
336    /// assert_eq!(rx.blocking_recv(), Some(10));
337    /// sender.join().unwrap();
338    /// ```
339    pub fn blocking_send(&self, value: T) -> Result<(), SendError<T>> {
340        internal::blocking(self.send(value))
341    }
342
343    /// Whether the channel is closed: the receiver was closed or dropped.
344    ///
345    /// ```
346    /// use nuclei::sync::mpsc;
347    ///
348    /// let (tx, rx) = mpsc::channel::<()>(42);
349    /// let tx2 = tx.clone();
350    /// assert!(!tx.is_closed());
351    /// drop(rx);
352    /// assert!(tx.is_closed() && tx2.is_closed());
353    /// ```
354    pub fn is_closed(&self) -> bool {
355        self.chan.is_closed()
356    }
357
358    /// Waits for capacity for one message and reserves it.
359    ///
360    /// A [`Permit`] tracks the reserved slot; [`Permit::send`] uses it, and
361    /// dropping the permit unused gives the slot back.
362    ///
363    /// # Errors
364    ///
365    /// A [`SendError`] if the receiver is closed or dropped, now or while
366    /// waiting.
367    ///
368    /// # Cancel safety
369    ///
370    /// Dropping the future gives up its place in the queue of waiters, and a
371    /// slot it was handed meanwhile goes on to the next one. No slot is held
372    /// by a dropped future.
373    ///
374    /// ```
375    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
376    /// # fn now<F: Future>(f: F) -> F::Output {
377    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
378    /// #         Poll::Ready(out) => out,
379    /// #         Poll::Pending => panic!("not ready"),
380    /// #     }
381    /// # }
382    /// use nuclei::sync::mpsc;
383    ///
384    /// let (tx, mut rx) = mpsc::channel(1);
385    /// let permit = now(tx.reserve()).unwrap();
386    /// assert!(tx.try_send(123).is_err(), "the only slot is reserved");
387    /// permit.send(456);
388    /// assert_eq!(rx.try_recv(), Ok(456));
389    /// ```
390    pub async fn reserve(&self) -> Result<Permit<'_, T>, SendError<()>> {
391        reserve_inner(&self.chan, 1).await?;
392        Ok(Permit::new(&self.chan))
393    }
394
395    /// Waits for capacity for `n` messages and reserves them.
396    ///
397    /// The returned [`PermitIterator`] yields `n` permits; dropping it before
398    /// it is exhausted gives the rest back. Waiting requests are served in the
399    /// order they began to wait, whatever each asks for: the slots that come
400    /// free are set aside for the oldest one until it has all `n`, and nothing
401    /// behind it is served first. Slots set aside for a request do not count
402    /// in [`capacity`](Self::capacity).
403    ///
404    /// # Errors
405    ///
406    /// A [`SendError`] if the receiver is closed or dropped, now or while
407    /// waiting, or if `n` is more than the channel can ever hold
408    /// ([`max_capacity`](Self::max_capacity)). `n == 0` succeeds with an empty
409    /// iterator unless the channel is closed.
410    ///
411    /// # Cancel safety
412    ///
413    /// As for [`reserve`](Self::reserve): the slots set aside for a dropped
414    /// request go on to the next one.
415    ///
416    /// ```
417    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
418    /// # fn now<F: Future>(f: F) -> F::Output {
419    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
420    /// #         Poll::Ready(out) => out,
421    /// #         Poll::Pending => panic!("not ready"),
422    /// #     }
423    /// # }
424    /// use nuclei::sync::mpsc;
425    ///
426    /// let (tx, mut rx) = mpsc::channel(2);
427    /// let mut permits = now(tx.reserve_many(2)).unwrap();
428    /// assert!(tx.try_send(123).is_err());
429    /// permits.next().unwrap().send(456);
430    /// permits.next().unwrap().send(457);
431    /// assert!(permits.next().is_none());
432    /// assert_eq!(rx.try_recv(), Ok(456));
433    /// assert_eq!(rx.try_recv(), Ok(457));
434    /// ```
435    pub async fn reserve_many(&self, n: usize) -> Result<PermitIterator<'_, T>, SendError<()>> {
436        reserve_inner(&self.chan, n).await?;
437        Ok(PermitIterator::new(&self.chan, n))
438    }
439
440    /// Waits for capacity for one message, moving the sender into the
441    /// returned [`OwnedPermit`].
442    ///
443    /// Unlike [`reserve`](Self::reserve), the permit borrows nothing, so it can
444    /// be stored or moved into another task. Cloning a sender first keeps a
445    /// handle to send with meanwhile. [`OwnedPermit::send`] and [`OwnedPermit::release`] hand
446    /// the sender back.
447    ///
448    /// # Errors
449    ///
450    /// A [`SendError`] if the receiver is closed or dropped, now or while
451    /// waiting.
452    ///
453    /// # Cancel safety
454    ///
455    /// Dropping the future gives up its place in the queue of waiters, passes
456    /// on a slot it was handed meanwhile, and drops the sender it holds.
457    ///
458    /// ```
459    /// # use std::{future::Future, pin::pin, task::{Context, Poll, Waker}};
460    /// # fn now<F: Future>(f: F) -> F::Output {
461    /// #     match pin!(f).poll(&mut Context::from_waker(Waker::noop())) {
462    /// #         Poll::Ready(out) => out,
463    /// #         Poll::Pending => panic!("not ready"),
464    /// #     }
465    /// # }
466    /// use nuclei::sync::mpsc;
467    ///
468    /// let (tx, mut rx) = mpsc::channel(1);
469    /// let permit = now(tx.reserve_owned()).unwrap();
470    /// let tx = permit.send(123);
471    /// assert_eq!(rx.try_recv(), Ok(123));
472    /// tx.try_send(456).unwrap();
473    /// ```
474    pub async fn reserve_owned(self) -> Result<OwnedPermit<T>, SendError<()>> {
475        reserve_inner(&self.chan, 1).await?;
476        Ok(OwnedPermit::new(self))
477    }
478
479    /// Reserves capacity for one message if there is any, without waiting.
480    /// It never takes a slot ahead of a send or reservation that is waiting.
481    ///
482    /// # Errors
483    ///
484    /// [`TrySendError::Full`] when no slot is free or a send or reservation
485    /// is waiting, [`TrySendError::Closed`] when the receiver closed or was
486    /// dropped.
487    ///
488    /// ```
489    /// use nuclei::sync::mpsc;
490    ///
491    /// let (tx, mut rx) = mpsc::channel(1);
492    /// let permit = tx.try_reserve().unwrap();
493    /// assert!(tx.try_reserve().is_err(), "no slot is left");
494    /// permit.send("foo");
495    /// assert_eq!(rx.try_recv(), Ok("foo"));
496    /// ```
497    pub fn try_reserve(&self) -> Result<Permit<'_, T>, TrySendError<()>> {
498        try_reserve_inner(&self.chan, 1)?;
499        Ok(Permit::new(&self.chan))
500    }
501
502    /// Reserves capacity for `n` messages if there is enough, without
503    /// waiting.
504    ///
505    /// # Errors
506    ///
507    /// [`TrySendError::Full`] when fewer than `n` slots are free, a send or
508    /// reservation is waiting, or `n` is more than the channel can ever hold;
509    /// [`TrySendError::Closed`] when the receiver closed or was dropped.
510    /// `n == 0` succeeds with an empty iterator unless the channel is closed.
511    ///
512    /// ```
513    /// use nuclei::sync::mpsc;
514    ///
515    /// let (tx, mut rx) = mpsc::channel(2);
516    /// let mut permits = tx.try_reserve_many(2).unwrap();
517    /// assert!(tx.try_send(123).is_err());
518    /// permits.next().unwrap().send(456);
519    /// permits.next().unwrap().send(457);
520    /// assert_eq!(rx.try_recv(), Ok(456));
521    /// assert_eq!(rx.try_recv(), Ok(457));
522    ///
523    /// assert!(tx.try_reserve_many(3).is_err(), "more than the channel holds");
524    /// ```
525    pub fn try_reserve_many(&self, n: usize) -> Result<PermitIterator<'_, T>, TrySendError<()>> {
526        if n > self.chan.limit.bound {
527            return Err(TrySendError::Full(()));
528        }
529        try_reserve_inner(&self.chan, n)?;
530        Ok(PermitIterator::new(&self.chan, n))
531    }
532
533    /// Reserves capacity for one message if there is any, moving the sender
534    /// into the returned [`OwnedPermit`].
535    ///
536    /// # Errors
537    ///
538    /// On failure the sender is handed back inside the error:
539    /// [`TrySendError::Full`] when no slot is free or a send or reservation
540    /// is waiting, [`TrySendError::Closed`] when the receiver closed or was
541    /// dropped.
542    ///
543    /// ```
544    /// use nuclei::sync::mpsc;
545    ///
546    /// let (tx, mut rx) = mpsc::channel(1);
547    /// let permit = tx.clone().try_reserve_owned().unwrap();
548    /// assert!(tx.try_send(123).is_err());
549    /// permit.send(456);
550    /// assert_eq!(rx.try_recv(), Ok(456));
551    /// ```
552    pub fn try_reserve_owned(self) -> Result<OwnedPermit<T>, TrySendError<Self>> {
553        match try_reserve_inner(&self.chan, 1) {
554            Ok(()) => Ok(OwnedPermit::new(self)),
555            Err(refused) => Err(refused.with_value(self)),
556        }
557    }
558
559    /// Whether two senders belong to the same channel.
560    ///
561    /// ```
562    /// use nuclei::sync::mpsc;
563    ///
564    /// let (tx, _rx) = mpsc::channel::<()>(1);
565    /// let tx2 = tx.clone();
566    /// assert!(tx.same_channel(&tx2));
567    ///
568    /// let (tx3, _rx3) = mpsc::channel::<()>(1);
569    /// assert!(!tx3.same_channel(&tx2));
570    /// ```
571    pub fn same_channel(&self, other: &Self) -> bool {
572        Arc::ptr_eq(&self.chan, &other.chan)
573    }
574
575    /// The channel's current capacity: the slots that are free.
576    ///
577    /// It goes down when a value is sent or a slot is reserved, and up when the
578    /// receiver takes a value or a permit is dropped unused. A slot set aside
579    /// for a waiting [`reserve_many`](Self::reserve_many) is not free. Compare
580    /// [`max_capacity`](Self::max_capacity), which never changes.
581    ///
582    /// ```
583    /// use nuclei::sync::mpsc;
584    ///
585    /// let (tx, mut rx) = mpsc::channel::<()>(5);
586    /// assert_eq!(tx.capacity(), 5);
587    /// let permit = tx.try_reserve().unwrap();
588    /// assert_eq!(tx.capacity(), 4);
589    /// permit.send(());
590    /// rx.try_recv().unwrap();
591    /// assert_eq!(tx.capacity(), 5);
592    /// ```
593    pub fn capacity(&self) -> usize {
594        self.chan.limit.sem.available()
595    }
596
597    /// Converts the sender into a [`WeakSender`], which does not keep the
598    /// channel open. The sender itself stays.
599    #[must_use = "Downgrade creates a WeakSender without destroying the original non-weak sender."]
600    pub fn downgrade(&self) -> WeakSender<T> {
601        self.chan.add_weak();
602        WeakSender {
603            chan: Arc::clone(&self.chan),
604        }
605    }
606
607    /// The channel's maximum capacity: the `buffer` it was created with.
608    ///
609    /// ```
610    /// use nuclei::sync::mpsc;
611    ///
612    /// let (tx, _rx) = mpsc::channel::<()>(5);
613    /// let _permit = tx.try_reserve().unwrap();
614    /// assert_eq!(tx.max_capacity(), 5);
615    /// assert_eq!(tx.capacity(), 4);
616    /// ```
617    pub fn max_capacity(&self) -> usize {
618        self.chan.limit.bound
619    }
620
621    /// How many [`Sender`] handles exist (an [`OwnedPermit`] holds one).
622    pub fn strong_count(&self) -> usize {
623        self.chan.strong_count()
624    }
625
626    /// How many [`WeakSender`] handles exist.
627    pub fn weak_count(&self) -> usize {
628        self.chan.weak_count()
629    }
630}
631
632impl<T> Clone for Sender<T> {
633    fn clone(&self) -> Self {
634        self.chan.add_sender();
635        Sender {
636            chan: Arc::clone(&self.chan),
637        }
638    }
639}
640
641impl<T> Drop for Sender<T> {
642    fn drop(&mut self) {
643        self.chan.drop_sender();
644    }
645}
646
647impl<T> fmt::Debug for Sender<T> {
648    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
649        f.debug_struct("Sender")
650            .field("closed", &self.is_closed())
651            .field("capacity", &self.capacity())
652            .field("max_capacity", &self.max_capacity())
653            .finish()
654    }
655}
656
657impl<T> WeakSender<T> {
658    /// Tries to turn the weak sender into a [`Sender`].
659    ///
660    /// Returns `Some` while at least one [`Sender`] (or [`OwnedPermit`]) is
661    /// alive, and `None` once the last is gone.
662    pub fn upgrade(&self) -> Option<Sender<T>> {
663        self.chan.try_add_sender().then(|| Sender {
664            chan: Arc::clone(&self.chan),
665        })
666    }
667
668    /// How many [`Sender`] handles exist.
669    pub fn strong_count(&self) -> usize {
670        self.chan.strong_count()
671    }
672
673    /// How many [`WeakSender`] handles exist.
674    pub fn weak_count(&self) -> usize {
675        self.chan.weak_count()
676    }
677}
678
679impl<T> Clone for WeakSender<T> {
680    fn clone(&self) -> Self {
681        self.chan.add_weak();
682        WeakSender {
683            chan: Arc::clone(&self.chan),
684        }
685    }
686}
687
688impl<T> Drop for WeakSender<T> {
689    fn drop(&mut self) {
690        self.chan.drop_weak();
691    }
692}
693
694impl<T> fmt::Debug for WeakSender<T> {
695    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
696        f.debug_struct("WeakSender").finish()
697    }
698}
699
700/// Takes `n` slots without waiting: the permits are the caller's to hand to
701/// [`Permit`]s, which return them.
702fn try_reserve_inner<T>(chan: &Chan<T, Bounded>, n: usize) -> Result<(), TrySendError<()>> {
703    match chan.limit.sem.try_acquire(n) {
704        Ok(()) => Ok(()),
705        Err(seen) if observed_closed(seen) => Err(TrySendError::Closed(())),
706        Err(_) => Err(TrySendError::Full(())),
707    }
708}
709
710/// Waits for `n` slots, which the caller then owns as [`Permit`]s.
711async fn reserve_inner<T>(chan: &Chan<T, Bounded>, n: usize) -> Result<(), SendError<()>> {
712    if n > chan.limit.bound {
713        return Err(SendError(()));
714    }
715    Reserve {
716        chan,
717        n,
718        wait: FairWait::new(),
719        taken: false,
720    }
721    .await
722}
723
724/// The future of [`Sender::send`]: the wait of [`reserve_inner`] for one
725/// slot and the push of the value into it, as one future, so a send that
726/// finds a slot free takes it and pushes with no state of nested waits.
727///
728/// It ends as a [`Reserve`] for one slot followed by a [`Permit`] send does:
729/// a wait that fails, or that is dropped before it completes, lets go of its
730/// place (and of a slot it was handed meanwhile) and wakes a receiver that
731/// waits for a closed channel to go idle; the value is dropped after that.
732struct Sending<'a, T> {
733    chan: &'a Chan<T, Bounded>,
734    wait: FairWait,
735    /// The value to send: taken when the wait ends, so `None` once the
736    /// future completed.
737    value: Option<T>,
738    /// Not `Unpin`, as the established API's send future is not.
739    _pinned: PhantomPinned,
740}
741
742impl<T> Sending<'_, T> {
743    /// What a [`Reserve`] that did not get its slot does as it is dropped.
744    fn let_go(&mut self) {
745        self.wait.cancel(&self.chan.limit.sem, 1);
746        self.chan.wake_if_finished();
747    }
748}
749
750impl<T> Future for Sending<'_, T> {
751    type Output = Result<(), SendError<T>>;
752
753    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
754        // SAFETY: nothing of the future is pinned in place: the wait's node
755        // lives in its queue's pool, and the value moves into the channel or
756        // back to the caller, never borrowed across polls.
757        let this = unsafe { self.get_unchecked_mut() };
758        if this.value.is_none() {
759            polled_after_completion();
760        }
761        let granted = core::task::ready!(this.wait.poll(&this.chan.limit.sem, 1, cx.waker()));
762        let Some(value) = this.value.take() else {
763            polled_after_completion();
764        };
765        match granted {
766            Ok(()) => {
767                // The slot goes to the value, as a permit's send does.
768                this.chan.send(value);
769                Poll::Ready(Ok(()))
770            }
771            Err(_) => {
772                this.let_go();
773                Poll::Ready(Err(SendError(value)))
774            }
775        }
776    }
777}
778
779impl<T> Drop for Sending<'_, T> {
780    fn drop(&mut self) {
781        if self.value.is_some() {
782            self.let_go();
783        }
784    }
785}
786
787/// A `send` future polled again after it completed, which the `Future`
788/// contract rules out.
789#[cold]
790#[expect(
791    clippy::panic,
792    reason = "polled after it completed, which the `Future` contract rules out"
793)]
794fn polled_after_completion() -> ! {
795    panic!("`Sender::send` polled after it completed");
796}
797
798/// The wait of [`reserve_inner`].
799///
800/// A wait that ends without its slots becoming the caller's (it failed, or
801/// it was dropped, perhaps just after a grant) can leave a closed channel
802/// idle once what it held is back, with no receiver call to notice: so its
803/// drop wakes a receiver that waits for a closed channel to go idle, after
804/// the wait has left the queue.
805struct Reserve<'a, T> {
806    chan: &'a Chan<T, Bounded>,
807    n: usize,
808    wait: FairWait,
809    /// The slots are the caller's: they leave with its permits.
810    taken: bool,
811}
812
813impl<T> Future for Reserve<'_, T> {
814    type Output = Result<(), SendError<()>>;
815
816    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
817        let this = self.get_mut();
818        this.wait
819            .poll(&this.chan.limit.sem, this.n, cx.waker())
820            .map(|taken| {
821                this.taken = taken.is_ok();
822                taken.map_err(|_| SendError(()))
823            })
824    }
825}
826
827impl<T> Drop for Reserve<'_, T> {
828    fn drop(&mut self) {
829        if !self.taken {
830            self.wait.cancel(&self.chan.limit.sem, self.n);
831            self.chan.wake_if_finished();
832        }
833    }
834}
835
836#[cfg(all(test, not(loom)))]
837mod tests {
838    use super::*;
839    use crate::sync::test_support::Polled;
840
841    #[test]
842    fn the_free_slots_plus_the_queued_values_are_the_buffer() {
843        let (tx, mut rx) = channel::<u32>(4);
844        let permit = tx.try_reserve().unwrap();
845        tx.try_send(1).unwrap();
846        assert_eq!(tx.capacity() + rx.len() + 1, 4);
847        permit.send(2);
848        assert_eq!(tx.capacity() + rx.len(), 4);
849        rx.try_recv().unwrap();
850        assert_eq!(tx.capacity() + rx.len(), 4);
851    }
852
853    #[test]
854    fn a_zero_buffer_is_refused() {
855        let refused = std::panic::catch_unwind(|| channel::<u8>(0));
856        assert!(refused.is_err());
857    }
858
859    #[test]
860    fn a_reserve_granted_then_dropped_after_the_close_wakes_the_receiver() {
861        let (tx, mut rx) = channel::<()>(1);
862        let held = tx.try_reserve().unwrap();
863        let mut reserve = Polled::new(tx.reserve());
864        reserve.pending();
865        drop(held);
866        assert_eq!(reserve.wakes(), 1, "the slot was granted to the waiter");
867        assert_eq!(tx.capacity(), 0);
868        rx.close();
869        let mut recv = Polled::new(rx.recv());
870        recv.pending();
871        drop(reserve);
872        assert_eq!(tx.capacity(), 1, "the granted slot came back");
873        assert_eq!(recv.wakes(), 1, "and the closed receiver was told");
874        assert_eq!(recv.ready(), None);
875    }
876
877    #[test]
878    fn a_failed_reserve_wakes_a_receiver_waiting_for_idle() {
879        let (tx, mut rx) = channel::<()>(1);
880        let permit = tx.try_reserve().unwrap();
881        let mut reserve = Polled::new(tx.reserve());
882        reserve.pending();
883        rx.close();
884        // The reservation was granted the error by the close.
885        assert!(reserve.wakes() >= 1);
886        assert!(matches!(reserve.ready(), Err(SendError(()))));
887        let mut recv = Polled::new(rx.recv());
888        recv.pending();
889        drop(permit);
890        assert_eq!(recv.wakes(), 1, "the last permit back ends the wait");
891        assert_eq!(recv.ready(), None);
892    }
893
894    #[test]
895    fn dropping_the_receiver_fails_a_waiting_reserve_with_the_value_kept() {
896        let (tx, rx) = channel::<String>(1);
897        tx.try_send("held".to_string()).unwrap();
898        let mut send = Polled::new(tx.send("kept".to_string()));
899        send.pending();
900        drop(rx);
901        let SendError(value) = send.ready().unwrap_err();
902        assert_eq!(value, "kept");
903    }
904}