Skip to content

Commit f1478c9

Browse files
bors[bot]Stjepan Glavina
andcommitted
Merge #260
260: Improve docs for select r=stjepang a=stjepang Co-authored-by: Stjepan Glavina <[email protected]>
2 parents 1e27873 + e9b9884 commit f1478c9

File tree

2 files changed

+66
-47
lines changed

2 files changed

+66
-47
lines changed

crossbeam-channel/src/select.rs

Lines changed: 63 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -502,44 +502,76 @@ fn run_ready(
502502
/// The [`select!`] macro is a convenience wrapper around `Select`. However, it cannot select over a
503503
/// dynamically created list of channel operations.
504504
///
505-
/// [`select!`]: macro.select.html
505+
/// Once a list of operations has been built with `Select`, there are two different ways of
506+
/// proceeding:
507+
///
508+
/// * Select an operation with [`try_select`], [`select`], or [`select_timeout`]. If successful,
509+
/// the returned selected operation has already begun and **must** be completed. If we don't
510+
/// complete it, a panic will occur.
511+
///
512+
/// * Wait for an operation to become ready with [`try_ready`], [`ready`], or [`ready_timeout`]. If
513+
/// successful, we may attempt to execute the operation, but are not obliged to. In fact, it's
514+
/// possible for another thread to make the operation not ready just before we try executing it,
515+
/// so it's wise to use a retry loop.
506516
///
507517
/// # Examples
508518
///
509-
/// Receive a message from a list of channels:
519+
/// Use [`select`] to receive a message from a list of receivers:
510520
///
511521
/// ```
512-
/// use std::thread;
513-
/// use std::time::Duration;
514-
/// use crossbeam_channel::{unbounded, Receiver, Select, Sender};
522+
/// use crossbeam_channel::{Receiver, RecvError, Select};
515523
///
516-
/// // Create 10 channels.
517-
/// let chans: Vec<(Sender<&str>, Receiver<&str>)> = (0..10)
518-
/// .map(|_| unbounded())
519-
/// .collect();
524+
/// fn recv_multiple<T>(rs: &[Receiver<T>]) -> Result<T, RecvError> {
525+
/// // Build a list of operations.
526+
/// let mut sel = Select::new();
527+
/// for r in rs {
528+
/// sel.recv(r);
529+
/// }
520530
///
521-
/// // Spawn a thread that delivers a message to the 5th channel after 1 second.
522-
/// let s = chans[5].0.clone();
523-
/// thread::spawn(move || {
524-
/// thread::sleep(Duration::from_secs(1));
525-
/// s.send("hello").unwrap();
526-
/// });
527-
///
528-
/// // Wait until a message is received from one of the channels.
529-
/// let mut sel = Select::new();
530-
/// for (_, r) in &chans {
531-
/// sel.recv(r);
531+
/// // Complete the selected operation.
532+
/// let oper = sel.select();
533+
/// let index = oper.index();
534+
/// oper.recv(&rs[index])
532535
/// }
533-
/// let oper = sel.select();
536+
/// ```
534537
///
535-
/// // Complete the selected operation.
536-
/// let index = oper.index();
537-
/// let r = &chans[index].1;
538-
/// let res = oper.recv(r);
538+
/// Use [`ready`] to receive a message from a list of receivers:
539539
///
540-
/// assert_eq!(index, 5);
541-
/// assert_eq!(res, Ok("hello"));
542540
/// ```
541+
/// use crossbeam_channel::{Receiver, RecvError, Select};
542+
///
543+
/// fn recv_multiple<T>(rs: &[Receiver<T>]) -> Result<T, RecvError> {
544+
/// // Build a list of operations.
545+
/// let mut sel = Select::new();
546+
/// for r in rs {
547+
/// sel.recv(r);
548+
/// }
549+
///
550+
/// loop {
551+
/// // Wait until a receive operation becomes ready and try executing it.
552+
/// let index = sel.ready();
553+
/// let res = rs[index].try_recv();
554+
///
555+
/// // If the operation turns out not to be ready, retry.
556+
/// if let Err(e) = res {
557+
/// if e.is_empty() {
558+
/// continue;
559+
/// }
560+
/// }
561+
///
562+
/// // Success!
563+
/// return res.map_err(|_| RecvError);
564+
/// }
565+
/// }
566+
/// ```
567+
///
568+
/// [`select!`]: macro.select.html
569+
/// [`try_select`]: struct.Select.html#method.try_select
570+
/// [`select`]: struct.Select.html#method.select
571+
/// [`select_timeout`]: struct.Select.html#method.select_timeout
572+
/// [`try_ready`]: struct.Select.html#method.try_ready
573+
/// [`ready`]: struct.Select.html#method.ready
574+
/// [`ready_timeout`]: struct.Select.html#method.ready_timeout
543575
pub struct Select<'a> {
544576
/// A list of senders and receivers participating in selection.
545577
handles: SmallVec<[(&'a SelectHandle, usize, *const u8); 4]>,
@@ -577,18 +609,10 @@ impl<'a> Select<'a> {
577609
/// use std::thread;
578610
/// use crossbeam_channel::{unbounded, Select};
579611
///
580-
/// let (s1, r1) = unbounded::<i32>();
581-
/// let (s2, r2) = unbounded::<i32>();
582-
/// let (s3, r3) = unbounded::<i32>();
612+
/// let (s, r) = unbounded::<i32>();
583613
///
584614
/// let mut sel = Select::new();
585-
/// let oper1 = sel.send(&s1);
586-
/// let oper2 = sel.send(&s2);
587-
/// let oper3 = sel.send(&s3);
588-
///
589-
/// assert_eq!(oper1, 0);
590-
/// assert_eq!(oper2, 1);
591-
/// assert_eq!(oper3, 2);
615+
/// let index = sel.send(&s);
592616
/// ```
593617
pub fn send<T>(&mut self, s: &'a Sender<T>) -> usize {
594618
let i = self.handles.len();
@@ -607,18 +631,10 @@ impl<'a> Select<'a> {
607631
/// use std::thread;
608632
/// use crossbeam_channel::{unbounded, Select};
609633
///
610-
/// let (s1, r1) = unbounded::<i32>();
611-
/// let (s2, r2) = unbounded::<i32>();
612-
/// let (s3, r3) = unbounded::<i32>();
634+
/// let (s, r) = unbounded::<i32>();
613635
///
614636
/// let mut sel = Select::new();
615-
/// let oper1 = sel.recv(&r1);
616-
/// let oper2 = sel.recv(&r2);
617-
/// let oper3 = sel.recv(&r3);
618-
///
619-
/// assert_eq!(oper1, 0);
620-
/// assert_eq!(oper2, 1);
621-
/// assert_eq!(oper3, 2);
637+
/// let index = sel.recv(&r);
622638
/// ```
623639
pub fn recv<T>(&mut self, r: &'a Receiver<T>) -> usize {
624640
let i = self.handles.len();

crossbeam-channel/src/select_macro.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,10 @@ macro_rules! crossbeam_channel_internal {
11871187
/// # }
11881188
/// ```
11891189
///
1190+
/// To optionally add a timeout to `select!`, see the [example] for [`never`].
1191+
///
11901192
/// [`never`]: fn.never.html
1193+
/// [example]: fn.never.html#examples
11911194
#[macro_export(local_inner_macros)]
11921195
macro_rules! select {
11931196
($($tokens:tt)*) => {

0 commit comments

Comments
 (0)