Skip to main content

crossbeam_channel/
channel.rs

1//! The channel interface.
2
3use std::fmt;
4use std::iter::FusedIterator;
5use std::mem;
6use std::panic::{RefUnwindSafe, UnwindSafe};
7use std::sync::Arc;
8use std::time::{Duration, Instant};
9
10use crate::context::Context;
11use crate::counter;
12use crate::err::{
13    RecvError, RecvTimeoutError, SendError, SendTimeoutError, TryRecvError, TrySendError,
14};
15use crate::flavors;
16use crate::select::{Operation, SelectHandle, Token};
17
18/// Creates a channel of unbounded capacity.
19///
20/// This channel has a growable buffer that can hold any number of messages at a time.
21///
22/// # Examples
23///
24/// ```
25/// use std::thread;
26/// use crossbeam_channel::unbounded;
27///
28/// let (s, r) = unbounded();
29///
30/// // Computes the n-th Fibonacci number.
31/// fn fib(n: i32) -> i32 {
32///     if n <= 1 {
33///         n
34///     } else {
35///         fib(n - 1) + fib(n - 2)
36///     }
37/// }
38///
39/// // Spawn an asynchronous computation.
40/// thread::spawn(move || s.send(fib(20)).unwrap());
41///
42/// // Print the result of the computation.
43/// println!("{}", r.recv().unwrap());
44/// ```
45pub fn unbounded<T>() -> (Sender<T>, Receiver<T>) {
46    let (s, r) = counter::new(flavors::list::Channel::new());
47    let s = Sender {
48        flavor: SenderFlavor::List(s),
49    };
50    let r = Receiver {
51        flavor: ReceiverFlavor::List(r),
52    };
53    (s, r)
54}
55
56/// Creates a channel of bounded capacity.
57///
58/// This channel has a buffer that can hold at most `cap` messages at a time.
59///
60/// A special case is zero-capacity channel, which cannot hold any messages. Instead, send and
61/// receive operations must appear at the same time in order to pair up and pass the message over.
62///
63/// # Examples
64///
65/// A channel of capacity 1:
66///
67/// ```
68/// use std::thread;
69/// use std::time::Duration;
70/// use crossbeam_channel::bounded;
71///
72/// let (s, r) = bounded(1);
73///
74/// // This call returns immediately because there is enough space in the channel.
75/// s.send(1).unwrap();
76///
77/// thread::spawn(move || {
78///     // This call blocks the current thread because the channel is full.
79///     // It will be able to complete only after the first message is received.
80///     s.send(2).unwrap();
81/// });
82///
83/// thread::sleep(Duration::from_secs(1));
84/// assert_eq!(r.recv(), Ok(1));
85/// assert_eq!(r.recv(), Ok(2));
86/// ```
87///
88/// A zero-capacity channel:
89///
90/// ```
91/// use std::thread;
92/// use std::time::Duration;
93/// use crossbeam_channel::bounded;
94///
95/// let (s, r) = bounded(0);
96///
97/// thread::spawn(move || {
98///     // This call blocks the current thread until a receive operation appears
99///     // on the other side of the channel.
100///     s.send(1).unwrap();
101/// });
102///
103/// thread::sleep(Duration::from_secs(1));
104/// assert_eq!(r.recv(), Ok(1));
105/// ```
106/// # Panics
107///
108/// Panics if `cap` is too large to initialize the bounded channel.
109pub fn bounded<T>(cap: usize) -> (Sender<T>, Receiver<T>) {
110    if cap == 0 {
111        let (s, r) = counter::new(flavors::zero::Channel::new());
112        let s = Sender {
113            flavor: SenderFlavor::Zero(s),
114        };
115        let r = Receiver {
116            flavor: ReceiverFlavor::Zero(r),
117        };
118        (s, r)
119    } else {
120        let (s, r) = counter::new(flavors::array::Channel::with_capacity(cap));
121        let s = Sender {
122            flavor: SenderFlavor::Array(s),
123        };
124        let r = Receiver {
125            flavor: ReceiverFlavor::Array(r),
126        };
127        (s, r)
128    }
129}
130
131/// Creates a receiver that delivers a message after a certain duration of time.
132///
133/// The channel is bounded with capacity of 1 and never gets disconnected. Exactly one message will
134/// be sent into the channel after `duration` elapses. The message is the instant at which it is
135/// sent.
136///
137/// # Examples
138///
139/// Using an `after` channel for timeouts:
140///
141/// ```
142/// use std::time::Duration;
143/// use crossbeam_channel::{after, select, unbounded};
144///
145/// let (s, r) = unbounded::<i32>();
146/// let timeout = Duration::from_millis(100);
147///
148/// select! {
149///     recv(r) -> msg => println!("received {:?}", msg),
150///     recv(after(timeout)) -> _ => println!("timed out"),
151/// }
152/// ```
153///
154/// When the message gets sent:
155///
156/// ```
157/// use std::thread;
158/// use std::time::{Duration, Instant};
159/// use crossbeam_channel::after;
160///
161/// // Converts a number of milliseconds into a `Duration`.
162/// let ms = |ms| Duration::from_millis(ms);
163///
164/// // Returns `true` if `a` and `b` are very close `Instant`s.
165/// let eq = |a, b| a + ms(60) > b && b + ms(60) > a;
166///
167/// let start = Instant::now();
168/// let r = after(ms(100));
169///
170/// thread::sleep(ms(500));
171///
172/// // This message was sent 100 ms from the start and received 500 ms from the start.
173/// assert!(eq(r.recv().unwrap(), start + ms(100)));
174/// assert!(eq(Instant::now(), start + ms(500)));
175/// ```
176pub fn after(duration: Duration) -> Receiver<Instant> {
177    match Instant::now().checked_add(duration) {
178        Some(deadline) => Receiver {
179            flavor: ReceiverFlavor::At(Arc::new(flavors::at::Channel::new_deadline(deadline))),
180        },
181        None => never(),
182    }
183}
184
185/// Creates a receiver that delivers a message at a certain instant in time.
186///
187/// The channel is bounded with capacity of 1 and never gets disconnected. Exactly one message will
188/// be sent into the channel at the moment in time `when`. The message is the instant at which it
189/// is sent, which is the same as `when`. If `when` is in the past, the message will be delivered
190/// instantly to the receiver.
191///
192/// # Examples
193///
194/// Using an `at` channel for timeouts:
195///
196/// ```
197/// use std::time::{Instant, Duration};
198/// use crossbeam_channel::{at, select, unbounded};
199///
200/// let (s, r) = unbounded::<i32>();
201/// let deadline = Instant::now() + Duration::from_millis(500);
202///
203/// select! {
204///     recv(r) -> msg => println!("received {:?}", msg),
205///     recv(at(deadline)) -> _ => println!("timed out"),
206/// }
207/// ```
208///
209/// When the message gets sent:
210///
211/// ```
212/// use std::time::{Duration, Instant};
213/// use crossbeam_channel::at;
214///
215/// // Converts a number of milliseconds into a `Duration`.
216/// let ms = |ms| Duration::from_millis(ms);
217///
218/// let start = Instant::now();
219/// let end = start + ms(100);
220///
221/// let r = at(end);
222///
223/// // This message was sent 100 ms from the start
224/// assert_eq!(r.recv().unwrap(), end);
225/// assert!(Instant::now() > start + ms(100));
226/// ```
227pub fn at(when: Instant) -> Receiver<Instant> {
228    Receiver {
229        flavor: ReceiverFlavor::At(Arc::new(flavors::at::Channel::new_deadline(when))),
230    }
231}
232
233/// Creates a receiver that never delivers messages.
234///
235/// The channel is bounded with capacity of 0 and never gets disconnected.
236///
237/// # Examples
238///
239/// Using a `never` channel to optionally add a timeout to [`select!`]:
240///
241/// [`select!`]: crate::select!
242///
243/// ```
244/// use std::thread;
245/// use std::time::Duration;
246/// use crossbeam_channel::{after, select, never, unbounded};
247///
248/// let (s, r) = unbounded();
249///
250/// thread::spawn(move || {
251///     thread::sleep(Duration::from_secs(1));
252///     s.send(1).unwrap();
253/// });
254///
255/// // Suppose this duration can be a `Some` or a `None`.
256/// let duration = Some(Duration::from_millis(100));
257///
258/// // Create a channel that times out after the specified duration.
259/// let timeout = duration
260///     .map(|d| after(d))
261///     .unwrap_or(never());
262///
263/// select! {
264///     recv(r) -> msg => assert_eq!(msg, Ok(1)),
265///     recv(timeout) -> _ => println!("timed out"),
266/// }
267/// ```
268pub const fn never<T>() -> Receiver<T> {
269    Receiver {
270        flavor: ReceiverFlavor::Never(flavors::never::Channel::new()),
271    }
272}
273
274/// Creates a receiver that delivers messages periodically.
275///
276/// The channel is bounded with capacity of 1 and never gets disconnected. Messages will be
277/// sent into the channel in intervals of `duration`. Each message is the instant at which it is
278/// sent.
279///
280/// # Examples
281///
282/// Using a `tick` channel to periodically print elapsed time:
283///
284/// ```
285/// use std::time::{Duration, Instant};
286/// use crossbeam_channel::tick;
287///
288/// let start = Instant::now();
289/// let ticker = tick(Duration::from_millis(100));
290///
291/// for _ in 0..5 {
292///     ticker.recv().unwrap();
293///     println!("elapsed: {:?}", start.elapsed());
294/// }
295/// ```
296///
297/// When messages get sent:
298///
299/// ```
300/// use std::thread;
301/// use std::time::{Duration, Instant};
302/// use crossbeam_channel::tick;
303///
304/// // Converts a number of milliseconds into a `Duration`.
305/// let ms = |ms| Duration::from_millis(ms);
306///
307/// // Returns `true` if `a` and `b` are very close `Instant`s.
308/// let eq = |a, b| a + ms(65) > b && b + ms(65) > a;
309///
310/// let start = Instant::now();
311/// let r = tick(ms(100));
312///
313/// // This message was sent 100 ms from the start and received 100 ms from the start.
314/// assert!(eq(r.recv().unwrap(), start + ms(100)));
315/// assert!(eq(Instant::now(), start + ms(100)));
316///
317/// thread::sleep(ms(500));
318///
319/// // This message was sent 200 ms from the start and received 600 ms from the start.
320/// assert!(eq(r.recv().unwrap(), start + ms(200)));
321/// assert!(eq(Instant::now(), start + ms(600)));
322///
323/// // This message was sent 700 ms from the start and received 700 ms from the start.
324/// assert!(eq(r.recv().unwrap(), start + ms(700)));
325/// assert!(eq(Instant::now(), start + ms(700)));
326/// ```
327pub fn tick(duration: Duration) -> Receiver<Instant> {
328    match Instant::now().checked_add(duration) {
329        Some(delivery_time) => Receiver {
330            flavor: ReceiverFlavor::Tick(Arc::new(flavors::tick::Channel::new(
331                delivery_time,
332                duration,
333            ))),
334        },
335        None => never(),
336    }
337}
338
339/// The sending side of a channel.
340///
341/// # Examples
342///
343/// ```
344/// use std::thread;
345/// use crossbeam_channel::unbounded;
346///
347/// let (s1, r) = unbounded();
348/// let s2 = s1.clone();
349///
350/// thread::spawn(move || s1.send(1).unwrap());
351/// thread::spawn(move || s2.send(2).unwrap());
352///
353/// let msg1 = r.recv().unwrap();
354/// let msg2 = r.recv().unwrap();
355///
356/// assert_eq!(msg1 + msg2, 3);
357/// ```
358pub struct Sender<T> {
359    flavor: SenderFlavor<T>,
360}
361
362/// Sender flavors.
363enum SenderFlavor<T> {
364    /// Bounded channel based on a preallocated array.
365    Array(counter::Sender<flavors::array::Channel<T>>),
366
367    /// Unbounded channel implemented as a linked list.
368    List(counter::Sender<flavors::list::Channel<T>>),
369
370    /// Zero-capacity channel.
371    Zero(counter::Sender<flavors::zero::Channel<T>>),
372}
373
374unsafe impl<T: Send> Send for Sender<T> {}
375unsafe impl<T: Send> Sync for Sender<T> {}
376
377impl<T> UnwindSafe for Sender<T> {}
378impl<T> RefUnwindSafe for Sender<T> {}
379
380impl<T> Sender<T> {
381    /// Attempts to send a message into the channel without blocking.
382    ///
383    /// This method will either send a message into the channel immediately or return an error if
384    /// the channel is full or disconnected. The returned error contains the original message.
385    ///
386    /// If called on a zero-capacity channel, this method will send the message only if there
387    /// happens to be a receive operation on the other side of the channel at the same time.
388    ///
389    /// # Examples
390    ///
391    /// ```
392    /// use crossbeam_channel::{bounded, TrySendError};
393    ///
394    /// let (s, r) = bounded(1);
395    ///
396    /// assert_eq!(s.try_send(1), Ok(()));
397    /// assert_eq!(s.try_send(2), Err(TrySendError::Full(2)));
398    ///
399    /// drop(r);
400    /// assert_eq!(s.try_send(3), Err(TrySendError::Disconnected(3)));
401    /// ```
402    pub fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
403        match &self.flavor {
404            SenderFlavor::Array(chan) => chan.try_send(msg),
405            SenderFlavor::List(chan) => chan.try_send(msg),
406            SenderFlavor::Zero(chan) => chan.try_send(msg),
407        }
408    }
409
410    /// Blocks the current thread until a message is sent or the channel is disconnected.
411    ///
412    /// If the channel is full and not disconnected, this call will block until the send operation
413    /// can proceed. If the channel becomes disconnected, this call will wake up and return an
414    /// error. The returned error contains the original message.
415    ///
416    /// If called on a zero-capacity channel, this method will wait for a receive operation to
417    /// appear on the other side of the channel.
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// use std::thread;
423    /// use std::time::Duration;
424    /// use crossbeam_channel::{bounded, SendError};
425    ///
426    /// let (s, r) = bounded(1);
427    /// assert_eq!(s.send(1), Ok(()));
428    ///
429    /// thread::spawn(move || {
430    ///     assert_eq!(r.recv(), Ok(1));
431    ///     thread::sleep(Duration::from_secs(1));
432    ///     drop(r);
433    /// });
434    ///
435    /// assert_eq!(s.send(2), Ok(()));
436    /// assert_eq!(s.send(3), Err(SendError(3)));
437    /// ```
438    pub fn send(&self, msg: T) -> Result<(), SendError<T>> {
439        match &self.flavor {
440            SenderFlavor::Array(chan) => chan.send(msg, None),
441            SenderFlavor::List(chan) => chan.send(msg, None),
442            SenderFlavor::Zero(chan) => chan.send(msg, None),
443        }
444        .map_err(|err| match err {
445            SendTimeoutError::Disconnected(msg) => SendError(msg),
446            SendTimeoutError::Timeout(_) => unreachable!(),
447        })
448    }
449
450    /// Waits for a message to be sent into the channel, but only for a limited time.
451    ///
452    /// If the channel is full and not disconnected, this call will block until the send operation
453    /// can proceed or the operation times out. If the channel becomes disconnected, this call will
454    /// wake up and return an error. The returned error contains the original message. If the
455    /// channel is not full and the timeout has already elapsed, the message will still be sent.
456    ///
457    /// If called on a zero-capacity channel, this method will wait for a receive operation to
458    /// appear on the other side of the channel.
459    ///
460    /// # Examples
461    ///
462    /// ```
463    /// use std::thread;
464    /// use std::time::Duration;
465    /// use crossbeam_channel::{bounded, SendTimeoutError};
466    ///
467    /// let (s, r) = bounded(0);
468    ///
469    /// thread::spawn(move || {
470    ///     thread::sleep(Duration::from_secs(1));
471    ///     assert_eq!(r.recv(), Ok(2));
472    ///     drop(r);
473    /// });
474    ///
475    /// assert_eq!(
476    ///     s.send_timeout(1, Duration::from_millis(500)),
477    ///     Err(SendTimeoutError::Timeout(1)),
478    /// );
479    /// assert_eq!(
480    ///     s.send_timeout(2, Duration::from_secs(1)),
481    ///     Ok(()),
482    /// );
483    /// assert_eq!(
484    ///     s.send_timeout(3, Duration::from_millis(500)),
485    ///     Err(SendTimeoutError::Disconnected(3)),
486    /// );
487    /// ```
488    pub fn send_timeout(&self, msg: T, timeout: Duration) -> Result<(), SendTimeoutError<T>> {
489        match Instant::now().checked_add(timeout) {
490            Some(deadline) => self.send_deadline(msg, deadline),
491            None => self.send(msg).map_err(SendTimeoutError::from),
492        }
493    }
494
495    /// Waits for a message to be sent into the channel, but only until a given deadline.
496    ///
497    /// If the channel is full and not disconnected, this call will block until the send operation
498    /// can proceed or the operation times out. If the channel becomes disconnected, this call will
499    /// wake up and return an error. The returned error contains the original message. If the
500    /// channel is not full and the deadline has already been reached, the message will still be
501    /// sent.
502    ///
503    /// If called on a zero-capacity channel, this method will wait for a receive operation to
504    /// appear on the other side of the channel.
505    ///
506    /// # Examples
507    ///
508    /// ```
509    /// use std::thread;
510    /// use std::time::{Duration, Instant};
511    /// use crossbeam_channel::{bounded, SendTimeoutError};
512    ///
513    /// let (s, r) = bounded(0);
514    ///
515    /// thread::spawn(move || {
516    ///     thread::sleep(Duration::from_secs(1));
517    ///     assert_eq!(r.recv(), Ok(2));
518    ///     drop(r);
519    /// });
520    ///
521    /// let now = Instant::now();
522    ///
523    /// assert_eq!(
524    ///     s.send_deadline(1, now + Duration::from_millis(500)),
525    ///     Err(SendTimeoutError::Timeout(1)),
526    /// );
527    /// assert_eq!(
528    ///     s.send_deadline(2, now + Duration::from_millis(1500)),
529    ///     Ok(()),
530    /// );
531    /// assert_eq!(
532    ///     s.send_deadline(3, now + Duration::from_millis(2000)),
533    ///     Err(SendTimeoutError::Disconnected(3)),
534    /// );
535    /// ```
536    pub fn send_deadline(&self, msg: T, deadline: Instant) -> Result<(), SendTimeoutError<T>> {
537        match &self.flavor {
538            SenderFlavor::Array(chan) => chan.send(msg, Some(deadline)),
539            SenderFlavor::List(chan) => chan.send(msg, Some(deadline)),
540            SenderFlavor::Zero(chan) => chan.send(msg, Some(deadline)),
541        }
542    }
543
544    /// Returns `true` if the channel is empty.
545    ///
546    /// Note: Zero-capacity channels are always empty.
547    ///
548    /// # Examples
549    ///
550    /// ```
551    /// use crossbeam_channel::unbounded;
552    ///
553    /// let (s, r) = unbounded();
554    /// assert!(s.is_empty());
555    ///
556    /// s.send(0).unwrap();
557    /// assert!(!s.is_empty());
558    /// ```
559    pub fn is_empty(&self) -> bool {
560        match &self.flavor {
561            SenderFlavor::Array(chan) => chan.is_empty(),
562            SenderFlavor::List(chan) => chan.is_empty(),
563            SenderFlavor::Zero(chan) => chan.is_empty(),
564        }
565    }
566
567    /// Returns `true` if the channel is full.
568    ///
569    /// Note: Zero-capacity channels are always full.
570    ///
571    /// # Examples
572    ///
573    /// ```
574    /// use crossbeam_channel::bounded;
575    ///
576    /// let (s, r) = bounded(1);
577    ///
578    /// assert!(!s.is_full());
579    /// s.send(0).unwrap();
580    /// assert!(s.is_full());
581    /// ```
582    pub fn is_full(&self) -> bool {
583        match &self.flavor {
584            SenderFlavor::Array(chan) => chan.is_full(),
585            SenderFlavor::List(chan) => chan.is_full(),
586            SenderFlavor::Zero(chan) => chan.is_full(),
587        }
588    }
589
590    /// Returns the number of messages in the channel.
591    ///
592    /// # Examples
593    ///
594    /// ```
595    /// use crossbeam_channel::unbounded;
596    ///
597    /// let (s, r) = unbounded();
598    /// assert_eq!(s.len(), 0);
599    ///
600    /// s.send(1).unwrap();
601    /// s.send(2).unwrap();
602    /// assert_eq!(s.len(), 2);
603    /// ```
604    pub fn len(&self) -> usize {
605        match &self.flavor {
606            SenderFlavor::Array(chan) => chan.len(),
607            SenderFlavor::List(chan) => chan.len(),
608            SenderFlavor::Zero(chan) => chan.len(),
609        }
610    }
611
612    /// If the channel is bounded, returns its capacity.
613    ///
614    /// # Examples
615    ///
616    /// ```
617    /// use crossbeam_channel::{bounded, unbounded};
618    ///
619    /// let (s, _) = unbounded::<i32>();
620    /// assert_eq!(s.capacity(), None);
621    ///
622    /// let (s, _) = bounded::<i32>(5);
623    /// assert_eq!(s.capacity(), Some(5));
624    ///
625    /// let (s, _) = bounded::<i32>(0);
626    /// assert_eq!(s.capacity(), Some(0));
627    /// ```
628    pub fn capacity(&self) -> Option<usize> {
629        match &self.flavor {
630            SenderFlavor::Array(chan) => chan.capacity(),
631            SenderFlavor::List(chan) => chan.capacity(),
632            SenderFlavor::Zero(chan) => chan.capacity(),
633        }
634    }
635
636    /// Returns `true` if senders belong to the same channel.
637    ///
638    /// # Examples
639    ///
640    /// ```rust
641    /// use crossbeam_channel::unbounded;
642    ///
643    /// let (s, _) = unbounded::<usize>();
644    ///
645    /// let s2 = s.clone();
646    /// assert!(s.same_channel(&s2));
647    ///
648    /// let (s3, _) = unbounded();
649    /// assert!(!s.same_channel(&s3));
650    /// ```
651    pub fn same_channel(&self, other: &Sender<T>) -> bool {
652        match (&self.flavor, &other.flavor) {
653            (SenderFlavor::Array(ref a), SenderFlavor::Array(ref b)) => a == b,
654            (SenderFlavor::List(ref a), SenderFlavor::List(ref b)) => a == b,
655            (SenderFlavor::Zero(ref a), SenderFlavor::Zero(ref b)) => a == b,
656            _ => false,
657        }
658    }
659}
660
661impl<T> Drop for Sender<T> {
662    fn drop(&mut self) {
663        unsafe {
664            match &self.flavor {
665                SenderFlavor::Array(chan) => chan.release(|c| c.disconnect()),
666                SenderFlavor::List(chan) => chan.release(|c| c.disconnect_senders()),
667                SenderFlavor::Zero(chan) => chan.release(|c| c.disconnect()),
668            }
669        }
670    }
671}
672
673impl<T> Clone for Sender<T> {
674    fn clone(&self) -> Self {
675        let flavor = match &self.flavor {
676            SenderFlavor::Array(chan) => SenderFlavor::Array(chan.acquire()),
677            SenderFlavor::List(chan) => SenderFlavor::List(chan.acquire()),
678            SenderFlavor::Zero(chan) => SenderFlavor::Zero(chan.acquire()),
679        };
680
681        Sender { flavor }
682    }
683}
684
685impl<T> fmt::Debug for Sender<T> {
686    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
687        f.pad("Sender { .. }")
688    }
689}
690
691/// The receiving side of a channel.
692///
693/// # Examples
694///
695/// ```
696/// use std::thread;
697/// use std::time::Duration;
698/// use crossbeam_channel::unbounded;
699///
700/// let (s, r) = unbounded();
701///
702/// thread::spawn(move || {
703///     let _ = s.send(1);
704///     thread::sleep(Duration::from_secs(1));
705///     let _ = s.send(2);
706/// });
707///
708/// assert_eq!(r.recv(), Ok(1)); // Received immediately.
709/// assert_eq!(r.recv(), Ok(2)); // Received after 1 second.
710/// ```
711pub struct Receiver<T> {
712    flavor: ReceiverFlavor<T>,
713}
714
715/// Receiver flavors.
716enum ReceiverFlavor<T> {
717    /// Bounded channel based on a preallocated array.
718    Array(counter::Receiver<flavors::array::Channel<T>>),
719
720    /// Unbounded channel implemented as a linked list.
721    List(counter::Receiver<flavors::list::Channel<T>>),
722
723    /// Zero-capacity channel.
724    Zero(counter::Receiver<flavors::zero::Channel<T>>),
725
726    /// The after flavor.
727    At(Arc<flavors::at::Channel>),
728
729    /// The tick flavor.
730    Tick(Arc<flavors::tick::Channel>),
731
732    /// The never flavor.
733    Never(flavors::never::Channel<T>),
734}
735
736unsafe impl<T: Send> Send for Receiver<T> {}
737unsafe impl<T: Send> Sync for Receiver<T> {}
738
739impl<T> UnwindSafe for Receiver<T> {}
740impl<T> RefUnwindSafe for Receiver<T> {}
741
742impl<T> Receiver<T> {
743    /// Attempts to receive a message from the channel without blocking.
744    ///
745    /// This method will either receive a message from the channel immediately or return an error
746    /// if the channel is empty.
747    ///
748    /// If called on a zero-capacity channel, this method will receive a message only if there
749    /// happens to be a send operation on the other side of the channel at the same time.
750    ///
751    /// # Examples
752    ///
753    /// ```
754    /// use crossbeam_channel::{unbounded, TryRecvError};
755    ///
756    /// let (s, r) = unbounded();
757    /// assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
758    ///
759    /// s.send(5).unwrap();
760    /// drop(s);
761    ///
762    /// assert_eq!(r.try_recv(), Ok(5));
763    /// assert_eq!(r.try_recv(), Err(TryRecvError::Disconnected));
764    /// ```
765    pub fn try_recv(&self) -> Result<T, TryRecvError> {
766        match &self.flavor {
767            ReceiverFlavor::Array(chan) => chan.try_recv(),
768            ReceiverFlavor::List(chan) => chan.try_recv(),
769            ReceiverFlavor::Zero(chan) => chan.try_recv(),
770            ReceiverFlavor::At(chan) => {
771                let msg = chan.try_recv();
772                unsafe {
773                    mem::transmute_copy::<Result<Instant, TryRecvError>, Result<T, TryRecvError>>(
774                        &msg,
775                    )
776                }
777            }
778            ReceiverFlavor::Tick(chan) => {
779                let msg = chan.try_recv();
780                unsafe {
781                    mem::transmute_copy::<Result<Instant, TryRecvError>, Result<T, TryRecvError>>(
782                        &msg,
783                    )
784                }
785            }
786            ReceiverFlavor::Never(chan) => chan.try_recv(),
787        }
788    }
789
790    /// Blocks the current thread until a message is received or the channel is empty and
791    /// disconnected.
792    ///
793    /// If the channel is empty and not disconnected, this call will block until the receive
794    /// operation can proceed. If the channel is empty and becomes disconnected, this call will
795    /// wake up and return an error.
796    ///
797    /// If called on a zero-capacity channel, this method will wait for a send operation to appear
798    /// on the other side of the channel.
799    ///
800    /// # Examples
801    ///
802    /// ```
803    /// use std::thread;
804    /// use std::time::Duration;
805    /// use crossbeam_channel::{unbounded, RecvError};
806    ///
807    /// let (s, r) = unbounded();
808    ///
809    /// thread::spawn(move || {
810    ///     thread::sleep(Duration::from_secs(1));
811    ///     s.send(5).unwrap();
812    ///     drop(s);
813    /// });
814    ///
815    /// assert_eq!(r.recv(), Ok(5));
816    /// assert_eq!(r.recv(), Err(RecvError));
817    /// ```
818    pub fn recv(&self) -> Result<T, RecvError> {
819        match &self.flavor {
820            ReceiverFlavor::Array(chan) => chan.recv(None),
821            ReceiverFlavor::List(chan) => chan.recv(None),
822            ReceiverFlavor::Zero(chan) => chan.recv(None),
823            ReceiverFlavor::At(chan) => {
824                let msg = chan.recv(None);
825                unsafe {
826                    mem::transmute_copy::<
827                        Result<Instant, RecvTimeoutError>,
828                        Result<T, RecvTimeoutError>,
829                    >(&msg)
830                }
831            }
832            ReceiverFlavor::Tick(chan) => {
833                let msg = chan.recv(None);
834                unsafe {
835                    mem::transmute_copy::<
836                        Result<Instant, RecvTimeoutError>,
837                        Result<T, RecvTimeoutError>,
838                    >(&msg)
839                }
840            }
841            ReceiverFlavor::Never(chan) => chan.recv(None),
842        }
843        .map_err(|_| RecvError)
844    }
845
846    /// Waits for a message to be received from the channel, but only for a limited time.
847    ///
848    /// If the channel is empty and not disconnected, this call will block until the receive
849    /// operation can proceed or the operation times out. If the channel is empty and becomes
850    /// disconnected, this call will wake up and return an error. If the channel is non-empty
851    /// and the timeout has already elapsed, the next message in the channel will be returned.
852    ///
853    /// If called on a zero-capacity channel, this method will wait for a send operation to appear
854    /// on the other side of the channel.
855    ///
856    /// # Examples
857    ///
858    /// ```
859    /// use std::thread;
860    /// use std::time::Duration;
861    /// use crossbeam_channel::{unbounded, RecvTimeoutError};
862    ///
863    /// let (s, r) = unbounded();
864    ///
865    /// thread::spawn(move || {
866    ///     thread::sleep(Duration::from_secs(1));
867    ///     s.send(5).unwrap();
868    ///     drop(s);
869    /// });
870    ///
871    /// assert_eq!(
872    ///     r.recv_timeout(Duration::from_millis(500)),
873    ///     Err(RecvTimeoutError::Timeout),
874    /// );
875    /// assert_eq!(
876    ///     r.recv_timeout(Duration::from_secs(1)),
877    ///     Ok(5),
878    /// );
879    /// assert_eq!(
880    ///     r.recv_timeout(Duration::from_secs(1)),
881    ///     Err(RecvTimeoutError::Disconnected),
882    /// );
883    /// ```
884    pub fn recv_timeout(&self, timeout: Duration) -> Result<T, RecvTimeoutError> {
885        match Instant::now().checked_add(timeout) {
886            Some(deadline) => self.recv_deadline(deadline),
887            None => self.recv().map_err(RecvTimeoutError::from),
888        }
889    }
890
891    /// Waits for a message to be received from the channel, but only before a given deadline.
892    ///
893    /// If the channel is empty and not disconnected, this call will block until the receive
894    /// operation can proceed or the operation times out. If the channel is empty and becomes
895    /// disconnected, this call will wake up and return an error. If the channel is non-empty
896    /// and the deadline has already been reached, the next message in the channel will be
897    /// returned.
898    ///
899    /// If called on a zero-capacity channel, this method will wait for a send operation to appear
900    /// on the other side of the channel.
901    ///
902    /// # Examples
903    ///
904    /// ```
905    /// use std::thread;
906    /// use std::time::{Instant, Duration};
907    /// use crossbeam_channel::{unbounded, RecvTimeoutError};
908    ///
909    /// let (s, r) = unbounded();
910    ///
911    /// thread::spawn(move || {
912    ///     thread::sleep(Duration::from_secs(1));
913    ///     s.send(5).unwrap();
914    ///     drop(s);
915    /// });
916    ///
917    /// let now = Instant::now();
918    ///
919    /// assert_eq!(
920    ///     r.recv_deadline(now + Duration::from_millis(500)),
921    ///     Err(RecvTimeoutError::Timeout),
922    /// );
923    /// assert_eq!(
924    ///     r.recv_deadline(now + Duration::from_millis(1500)),
925    ///     Ok(5),
926    /// );
927    /// assert_eq!(
928    ///     r.recv_deadline(now + Duration::from_secs(5)),
929    ///     Err(RecvTimeoutError::Disconnected),
930    /// );
931    /// ```
932    pub fn recv_deadline(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
933        match &self.flavor {
934            ReceiverFlavor::Array(chan) => chan.recv(Some(deadline)),
935            ReceiverFlavor::List(chan) => chan.recv(Some(deadline)),
936            ReceiverFlavor::Zero(chan) => chan.recv(Some(deadline)),
937            ReceiverFlavor::At(chan) => {
938                let msg = chan.recv(Some(deadline));
939                unsafe {
940                    mem::transmute_copy::<
941                        Result<Instant, RecvTimeoutError>,
942                        Result<T, RecvTimeoutError>,
943                    >(&msg)
944                }
945            }
946            ReceiverFlavor::Tick(chan) => {
947                let msg = chan.recv(Some(deadline));
948                unsafe {
949                    mem::transmute_copy::<
950                        Result<Instant, RecvTimeoutError>,
951                        Result<T, RecvTimeoutError>,
952                    >(&msg)
953                }
954            }
955            ReceiverFlavor::Never(chan) => chan.recv(Some(deadline)),
956        }
957    }
958
959    /// Returns `true` if the channel is empty.
960    ///
961    /// Note: Zero-capacity channels are always empty.
962    ///
963    /// # Examples
964    ///
965    /// ```
966    /// use crossbeam_channel::unbounded;
967    ///
968    /// let (s, r) = unbounded();
969    ///
970    /// assert!(r.is_empty());
971    /// s.send(0).unwrap();
972    /// assert!(!r.is_empty());
973    /// ```
974    pub fn is_empty(&self) -> bool {
975        match &self.flavor {
976            ReceiverFlavor::Array(chan) => chan.is_empty(),
977            ReceiverFlavor::List(chan) => chan.is_empty(),
978            ReceiverFlavor::Zero(chan) => chan.is_empty(),
979            ReceiverFlavor::At(chan) => chan.is_empty(),
980            ReceiverFlavor::Tick(chan) => chan.is_empty(),
981            ReceiverFlavor::Never(chan) => chan.is_empty(),
982        }
983    }
984
985    /// Returns `true` if the channel is full.
986    ///
987    /// Note: Zero-capacity channels are always full.
988    ///
989    /// # Examples
990    ///
991    /// ```
992    /// use crossbeam_channel::bounded;
993    ///
994    /// let (s, r) = bounded(1);
995    ///
996    /// assert!(!r.is_full());
997    /// s.send(0).unwrap();
998    /// assert!(r.is_full());
999    /// ```
1000    pub fn is_full(&self) -> bool {
1001        match &self.flavor {
1002            ReceiverFlavor::Array(chan) => chan.is_full(),
1003            ReceiverFlavor::List(chan) => chan.is_full(),
1004            ReceiverFlavor::Zero(chan) => chan.is_full(),
1005            ReceiverFlavor::At(chan) => chan.is_full(),
1006            ReceiverFlavor::Tick(chan) => chan.is_full(),
1007            ReceiverFlavor::Never(chan) => chan.is_full(),
1008        }
1009    }
1010
1011    /// Returns the number of messages in the channel.
1012    ///
1013    /// # Examples
1014    ///
1015    /// ```
1016    /// use crossbeam_channel::unbounded;
1017    ///
1018    /// let (s, r) = unbounded();
1019    /// assert_eq!(r.len(), 0);
1020    ///
1021    /// s.send(1).unwrap();
1022    /// s.send(2).unwrap();
1023    /// assert_eq!(r.len(), 2);
1024    /// ```
1025    pub fn len(&self) -> usize {
1026        match &self.flavor {
1027            ReceiverFlavor::Array(chan) => chan.len(),
1028            ReceiverFlavor::List(chan) => chan.len(),
1029            ReceiverFlavor::Zero(chan) => chan.len(),
1030            ReceiverFlavor::At(chan) => chan.len(),
1031            ReceiverFlavor::Tick(chan) => chan.len(),
1032            ReceiverFlavor::Never(chan) => chan.len(),
1033        }
1034    }
1035
1036    /// If the channel is bounded, returns its capacity.
1037    ///
1038    /// # Examples
1039    ///
1040    /// ```
1041    /// use crossbeam_channel::{bounded, unbounded};
1042    ///
1043    /// let (_, r) = unbounded::<i32>();
1044    /// assert_eq!(r.capacity(), None);
1045    ///
1046    /// let (_, r) = bounded::<i32>(5);
1047    /// assert_eq!(r.capacity(), Some(5));
1048    ///
1049    /// let (_, r) = bounded::<i32>(0);
1050    /// assert_eq!(r.capacity(), Some(0));
1051    /// ```
1052    pub fn capacity(&self) -> Option<usize> {
1053        match &self.flavor {
1054            ReceiverFlavor::Array(chan) => chan.capacity(),
1055            ReceiverFlavor::List(chan) => chan.capacity(),
1056            ReceiverFlavor::Zero(chan) => chan.capacity(),
1057            ReceiverFlavor::At(chan) => chan.capacity(),
1058            ReceiverFlavor::Tick(chan) => chan.capacity(),
1059            ReceiverFlavor::Never(chan) => chan.capacity(),
1060        }
1061    }
1062
1063    /// A blocking iterator over messages in the channel.
1064    ///
1065    /// Each call to [`next`] blocks waiting for the next message and then returns it. However, if
1066    /// the channel becomes empty and disconnected, it returns [`None`] without blocking.
1067    ///
1068    /// [`next`]: Iterator::next
1069    ///
1070    /// # Examples
1071    ///
1072    /// ```
1073    /// use std::thread;
1074    /// use crossbeam_channel::unbounded;
1075    ///
1076    /// let (s, r) = unbounded();
1077    ///
1078    /// thread::spawn(move || {
1079    ///     s.send(1).unwrap();
1080    ///     s.send(2).unwrap();
1081    ///     s.send(3).unwrap();
1082    ///     drop(s); // Disconnect the channel.
1083    /// });
1084    ///
1085    /// // Collect all messages from the channel.
1086    /// // Note that the call to `collect` blocks until the sender is dropped.
1087    /// let v: Vec<_> = r.iter().collect();
1088    ///
1089    /// assert_eq!(v, [1, 2, 3]);
1090    /// ```
1091    pub fn iter(&self) -> Iter<'_, T> {
1092        Iter { receiver: self }
1093    }
1094
1095    /// A non-blocking iterator over messages in the channel.
1096    ///
1097    /// Each call to [`next`] returns a message if there is one ready to be received. The iterator
1098    /// never blocks waiting for the next message.
1099    ///
1100    /// [`next`]: Iterator::next
1101    ///
1102    /// # Examples
1103    ///
1104    /// ```
1105    /// use std::thread;
1106    /// use std::time::Duration;
1107    /// use crossbeam_channel::unbounded;
1108    ///
1109    /// let (s, r) = unbounded::<i32>();
1110    ///
1111    /// thread::spawn(move || {
1112    ///     s.send(1).unwrap();
1113    ///     thread::sleep(Duration::from_secs(1));
1114    ///     s.send(2).unwrap();
1115    ///     thread::sleep(Duration::from_secs(2));
1116    ///     s.send(3).unwrap();
1117    /// });
1118    ///
1119    /// thread::sleep(Duration::from_secs(2));
1120    ///
1121    /// // Collect all messages from the channel without blocking.
1122    /// // The third message hasn't been sent yet so we'll collect only the first two.
1123    /// let v: Vec<_> = r.try_iter().collect();
1124    ///
1125    /// assert_eq!(v, [1, 2]);
1126    /// ```
1127    pub fn try_iter(&self) -> TryIter<'_, T> {
1128        TryIter { receiver: self }
1129    }
1130
1131    /// Returns `true` if receivers belong to the same channel.
1132    ///
1133    /// # Examples
1134    ///
1135    /// ```rust
1136    /// use crossbeam_channel::unbounded;
1137    ///
1138    /// let (_, r) = unbounded::<usize>();
1139    ///
1140    /// let r2 = r.clone();
1141    /// assert!(r.same_channel(&r2));
1142    ///
1143    /// let (_, r3) = unbounded();
1144    /// assert!(!r.same_channel(&r3));
1145    /// ```
1146    pub fn same_channel(&self, other: &Receiver<T>) -> bool {
1147        match (&self.flavor, &other.flavor) {
1148            (ReceiverFlavor::Array(a), ReceiverFlavor::Array(b)) => a == b,
1149            (ReceiverFlavor::List(a), ReceiverFlavor::List(b)) => a == b,
1150            (ReceiverFlavor::Zero(a), ReceiverFlavor::Zero(b)) => a == b,
1151            (ReceiverFlavor::At(a), ReceiverFlavor::At(b)) => Arc::ptr_eq(a, b),
1152            (ReceiverFlavor::Tick(a), ReceiverFlavor::Tick(b)) => Arc::ptr_eq(a, b),
1153            (ReceiverFlavor::Never(_), ReceiverFlavor::Never(_)) => true,
1154            _ => false,
1155        }
1156    }
1157}
1158
1159impl<T> Drop for Receiver<T> {
1160    fn drop(&mut self) {
1161        unsafe {
1162            match &self.flavor {
1163                ReceiverFlavor::Array(chan) => chan.release(|c| c.disconnect()),
1164                ReceiverFlavor::List(chan) => chan.release(|c| c.disconnect_receivers()),
1165                ReceiverFlavor::Zero(chan) => chan.release(|c| c.disconnect()),
1166                ReceiverFlavor::At(_) => {}
1167                ReceiverFlavor::Tick(_) => {}
1168                ReceiverFlavor::Never(_) => {}
1169            }
1170        }
1171    }
1172}
1173
1174impl<T> Clone for Receiver<T> {
1175    fn clone(&self) -> Self {
1176        let flavor = match &self.flavor {
1177            ReceiverFlavor::Array(chan) => ReceiverFlavor::Array(chan.acquire()),
1178            ReceiverFlavor::List(chan) => ReceiverFlavor::List(chan.acquire()),
1179            ReceiverFlavor::Zero(chan) => ReceiverFlavor::Zero(chan.acquire()),
1180            ReceiverFlavor::At(chan) => ReceiverFlavor::At(chan.clone()),
1181            ReceiverFlavor::Tick(chan) => ReceiverFlavor::Tick(chan.clone()),
1182            ReceiverFlavor::Never(_) => ReceiverFlavor::Never(flavors::never::Channel::new()),
1183        };
1184
1185        Receiver { flavor }
1186    }
1187}
1188
1189impl<T> fmt::Debug for Receiver<T> {
1190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191        f.pad("Receiver { .. }")
1192    }
1193}
1194
1195impl<'a, T> IntoIterator for &'a Receiver<T> {
1196    type Item = T;
1197    type IntoIter = Iter<'a, T>;
1198
1199    fn into_iter(self) -> Self::IntoIter {
1200        self.iter()
1201    }
1202}
1203
1204impl<T> IntoIterator for Receiver<T> {
1205    type Item = T;
1206    type IntoIter = IntoIter<T>;
1207
1208    fn into_iter(self) -> Self::IntoIter {
1209        IntoIter { receiver: self }
1210    }
1211}
1212
1213/// A blocking iterator over messages in a channel.
1214///
1215/// Each call to [`next`] blocks waiting for the next message and then returns it. However, if the
1216/// channel becomes empty and disconnected, it returns [`None`] without blocking.
1217///
1218/// [`next`]: Iterator::next
1219///
1220/// # Examples
1221///
1222/// ```
1223/// use std::thread;
1224/// use crossbeam_channel::unbounded;
1225///
1226/// let (s, r) = unbounded();
1227///
1228/// thread::spawn(move || {
1229///     s.send(1).unwrap();
1230///     s.send(2).unwrap();
1231///     s.send(3).unwrap();
1232///     drop(s); // Disconnect the channel.
1233/// });
1234///
1235/// // Collect all messages from the channel.
1236/// // Note that the call to `collect` blocks until the sender is dropped.
1237/// let v: Vec<_> = r.iter().collect();
1238///
1239/// assert_eq!(v, [1, 2, 3]);
1240/// ```
1241pub struct Iter<'a, T> {
1242    receiver: &'a Receiver<T>,
1243}
1244
1245impl<T> FusedIterator for Iter<'_, T> {}
1246
1247impl<T> Iterator for Iter<'_, T> {
1248    type Item = T;
1249
1250    fn next(&mut self) -> Option<Self::Item> {
1251        self.receiver.recv().ok()
1252    }
1253}
1254
1255impl<T> fmt::Debug for Iter<'_, T> {
1256    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1257        f.pad("Iter { .. }")
1258    }
1259}
1260
1261/// A non-blocking iterator over messages in a channel.
1262///
1263/// Each call to [`next`] returns a message if there is one ready to be received. The iterator
1264/// never blocks waiting for the next message.
1265///
1266/// [`next`]: Iterator::next
1267///
1268/// # Examples
1269///
1270/// ```
1271/// use std::thread;
1272/// use std::time::Duration;
1273/// use crossbeam_channel::unbounded;
1274///
1275/// let (s, r) = unbounded::<i32>();
1276///
1277/// thread::spawn(move || {
1278///     s.send(1).unwrap();
1279///     thread::sleep(Duration::from_secs(1));
1280///     s.send(2).unwrap();
1281///     thread::sleep(Duration::from_secs(2));
1282///     s.send(3).unwrap();
1283/// });
1284///
1285/// thread::sleep(Duration::from_secs(2));
1286///
1287/// // Collect all messages from the channel without blocking.
1288/// // The third message hasn't been sent yet so we'll collect only the first two.
1289/// let v: Vec<_> = r.try_iter().collect();
1290///
1291/// assert_eq!(v, [1, 2]);
1292/// ```
1293pub struct TryIter<'a, T> {
1294    receiver: &'a Receiver<T>,
1295}
1296
1297impl<T> Iterator for TryIter<'_, T> {
1298    type Item = T;
1299
1300    fn next(&mut self) -> Option<Self::Item> {
1301        self.receiver.try_recv().ok()
1302    }
1303}
1304
1305impl<T> fmt::Debug for TryIter<'_, T> {
1306    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1307        f.pad("TryIter { .. }")
1308    }
1309}
1310
1311/// A blocking iterator over messages in a channel.
1312///
1313/// Each call to [`next`] blocks waiting for the next message and then returns it. However, if the
1314/// channel becomes empty and disconnected, it returns [`None`] without blocking.
1315///
1316/// [`next`]: Iterator::next
1317///
1318/// # Examples
1319///
1320/// ```
1321/// use std::thread;
1322/// use crossbeam_channel::unbounded;
1323///
1324/// let (s, r) = unbounded();
1325///
1326/// thread::spawn(move || {
1327///     s.send(1).unwrap();
1328///     s.send(2).unwrap();
1329///     s.send(3).unwrap();
1330///     drop(s); // Disconnect the channel.
1331/// });
1332///
1333/// // Collect all messages from the channel.
1334/// // Note that the call to `collect` blocks until the sender is dropped.
1335/// let v: Vec<_> = r.into_iter().collect();
1336///
1337/// assert_eq!(v, [1, 2, 3]);
1338/// ```
1339pub struct IntoIter<T> {
1340    receiver: Receiver<T>,
1341}
1342
1343impl<T> FusedIterator for IntoIter<T> {}
1344
1345impl<T> Iterator for IntoIter<T> {
1346    type Item = T;
1347
1348    fn next(&mut self) -> Option<Self::Item> {
1349        self.receiver.recv().ok()
1350    }
1351}
1352
1353impl<T> fmt::Debug for IntoIter<T> {
1354    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1355        f.pad("IntoIter { .. }")
1356    }
1357}
1358
1359impl<T> SelectHandle for Sender<T> {
1360    fn try_select(&self, token: &mut Token) -> bool {
1361        match &self.flavor {
1362            SenderFlavor::Array(chan) => chan.sender().try_select(token),
1363            SenderFlavor::List(chan) => chan.sender().try_select(token),
1364            SenderFlavor::Zero(chan) => chan.sender().try_select(token),
1365        }
1366    }
1367
1368    fn deadline(&self) -> Option<Instant> {
1369        None
1370    }
1371
1372    fn register(&self, oper: Operation, cx: &Context) -> bool {
1373        match &self.flavor {
1374            SenderFlavor::Array(chan) => chan.sender().register(oper, cx),
1375            SenderFlavor::List(chan) => chan.sender().register(oper, cx),
1376            SenderFlavor::Zero(chan) => chan.sender().register(oper, cx),
1377        }
1378    }
1379
1380    fn unregister(&self, oper: Operation) {
1381        match &self.flavor {
1382            SenderFlavor::Array(chan) => chan.sender().unregister(oper),
1383            SenderFlavor::List(chan) => chan.sender().unregister(oper),
1384            SenderFlavor::Zero(chan) => chan.sender().unregister(oper),
1385        }
1386    }
1387
1388    fn accept(&self, token: &mut Token, cx: &Context) -> bool {
1389        match &self.flavor {
1390            SenderFlavor::Array(chan) => chan.sender().accept(token, cx),
1391            SenderFlavor::List(chan) => chan.sender().accept(token, cx),
1392            SenderFlavor::Zero(chan) => chan.sender().accept(token, cx),
1393        }
1394    }
1395
1396    fn is_ready(&self) -> bool {
1397        match &self.flavor {
1398            SenderFlavor::Array(chan) => chan.sender().is_ready(),
1399            SenderFlavor::List(chan) => chan.sender().is_ready(),
1400            SenderFlavor::Zero(chan) => chan.sender().is_ready(),
1401        }
1402    }
1403
1404    fn watch(&self, oper: Operation, cx: &Context) -> bool {
1405        match &self.flavor {
1406            SenderFlavor::Array(chan) => chan.sender().watch(oper, cx),
1407            SenderFlavor::List(chan) => chan.sender().watch(oper, cx),
1408            SenderFlavor::Zero(chan) => chan.sender().watch(oper, cx),
1409        }
1410    }
1411
1412    fn unwatch(&self, oper: Operation) {
1413        match &self.flavor {
1414            SenderFlavor::Array(chan) => chan.sender().unwatch(oper),
1415            SenderFlavor::List(chan) => chan.sender().unwatch(oper),
1416            SenderFlavor::Zero(chan) => chan.sender().unwatch(oper),
1417        }
1418    }
1419}
1420
1421impl<T> SelectHandle for Receiver<T> {
1422    fn try_select(&self, token: &mut Token) -> bool {
1423        match &self.flavor {
1424            ReceiverFlavor::Array(chan) => chan.receiver().try_select(token),
1425            ReceiverFlavor::List(chan) => chan.receiver().try_select(token),
1426            ReceiverFlavor::Zero(chan) => chan.receiver().try_select(token),
1427            ReceiverFlavor::At(chan) => chan.try_select(token),
1428            ReceiverFlavor::Tick(chan) => chan.try_select(token),
1429            ReceiverFlavor::Never(chan) => chan.try_select(token),
1430        }
1431    }
1432
1433    fn deadline(&self) -> Option<Instant> {
1434        match &self.flavor {
1435            ReceiverFlavor::Array(_) => None,
1436            ReceiverFlavor::List(_) => None,
1437            ReceiverFlavor::Zero(_) => None,
1438            ReceiverFlavor::At(chan) => chan.deadline(),
1439            ReceiverFlavor::Tick(chan) => chan.deadline(),
1440            ReceiverFlavor::Never(chan) => chan.deadline(),
1441        }
1442    }
1443
1444    fn register(&self, oper: Operation, cx: &Context) -> bool {
1445        match &self.flavor {
1446            ReceiverFlavor::Array(chan) => chan.receiver().register(oper, cx),
1447            ReceiverFlavor::List(chan) => chan.receiver().register(oper, cx),
1448            ReceiverFlavor::Zero(chan) => chan.receiver().register(oper, cx),
1449            ReceiverFlavor::At(chan) => chan.register(oper, cx),
1450            ReceiverFlavor::Tick(chan) => chan.register(oper, cx),
1451            ReceiverFlavor::Never(chan) => chan.register(oper, cx),
1452        }
1453    }
1454
1455    fn unregister(&self, oper: Operation) {
1456        match &self.flavor {
1457            ReceiverFlavor::Array(chan) => chan.receiver().unregister(oper),
1458            ReceiverFlavor::List(chan) => chan.receiver().unregister(oper),
1459            ReceiverFlavor::Zero(chan) => chan.receiver().unregister(oper),
1460            ReceiverFlavor::At(chan) => chan.unregister(oper),
1461            ReceiverFlavor::Tick(chan) => chan.unregister(oper),
1462            ReceiverFlavor::Never(chan) => chan.unregister(oper),
1463        }
1464    }
1465
1466    fn accept(&self, token: &mut Token, cx: &Context) -> bool {
1467        match &self.flavor {
1468            ReceiverFlavor::Array(chan) => chan.receiver().accept(token, cx),
1469            ReceiverFlavor::List(chan) => chan.receiver().accept(token, cx),
1470            ReceiverFlavor::Zero(chan) => chan.receiver().accept(token, cx),
1471            ReceiverFlavor::At(chan) => chan.accept(token, cx),
1472            ReceiverFlavor::Tick(chan) => chan.accept(token, cx),
1473            ReceiverFlavor::Never(chan) => chan.accept(token, cx),
1474        }
1475    }
1476
1477    fn is_ready(&self) -> bool {
1478        match &self.flavor {
1479            ReceiverFlavor::Array(chan) => chan.receiver().is_ready(),
1480            ReceiverFlavor::List(chan) => chan.receiver().is_ready(),
1481            ReceiverFlavor::Zero(chan) => chan.receiver().is_ready(),
1482            ReceiverFlavor::At(chan) => chan.is_ready(),
1483            ReceiverFlavor::Tick(chan) => chan.is_ready(),
1484            ReceiverFlavor::Never(chan) => chan.is_ready(),
1485        }
1486    }
1487
1488    fn watch(&self, oper: Operation, cx: &Context) -> bool {
1489        match &self.flavor {
1490            ReceiverFlavor::Array(chan) => chan.receiver().watch(oper, cx),
1491            ReceiverFlavor::List(chan) => chan.receiver().watch(oper, cx),
1492            ReceiverFlavor::Zero(chan) => chan.receiver().watch(oper, cx),
1493            ReceiverFlavor::At(chan) => chan.watch(oper, cx),
1494            ReceiverFlavor::Tick(chan) => chan.watch(oper, cx),
1495            ReceiverFlavor::Never(chan) => chan.watch(oper, cx),
1496        }
1497    }
1498
1499    fn unwatch(&self, oper: Operation) {
1500        match &self.flavor {
1501            ReceiverFlavor::Array(chan) => chan.receiver().unwatch(oper),
1502            ReceiverFlavor::List(chan) => chan.receiver().unwatch(oper),
1503            ReceiverFlavor::Zero(chan) => chan.receiver().unwatch(oper),
1504            ReceiverFlavor::At(chan) => chan.unwatch(oper),
1505            ReceiverFlavor::Tick(chan) => chan.unwatch(oper),
1506            ReceiverFlavor::Never(chan) => chan.unwatch(oper),
1507        }
1508    }
1509}
1510
1511/// Writes a message into the channel.
1512pub(crate) unsafe fn write<T>(s: &Sender<T>, token: &mut Token, msg: T) -> Result<(), T> {
1513    match &s.flavor {
1514        SenderFlavor::Array(chan) => chan.write(token, msg),
1515        SenderFlavor::List(chan) => chan.write(token, msg),
1516        SenderFlavor::Zero(chan) => chan.write(token, msg),
1517    }
1518}
1519
1520/// Reads a message from the channel.
1521pub(crate) unsafe fn read<T>(r: &Receiver<T>, token: &mut Token) -> Result<T, ()> {
1522    match &r.flavor {
1523        ReceiverFlavor::Array(chan) => chan.read(token),
1524        ReceiverFlavor::List(chan) => chan.read(token),
1525        ReceiverFlavor::Zero(chan) => chan.read(token),
1526        ReceiverFlavor::At(chan) => {
1527            mem::transmute_copy::<Result<Instant, ()>, Result<T, ()>>(&chan.read(token))
1528        }
1529        ReceiverFlavor::Tick(chan) => {
1530            mem::transmute_copy::<Result<Instant, ()>, Result<T, ()>>(&chan.read(token))
1531        }
1532        ReceiverFlavor::Never(chan) => chan.read(token),
1533    }
1534}