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}