summaryrefslogtreecommitdiffstats
path: root/third_party/rust/crossbeam-channel/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/crossbeam-channel/src/lib.rs')
-rw-r--r--third_party/rust/crossbeam-channel/src/lib.rs371
1 files changed, 371 insertions, 0 deletions
diff --git a/third_party/rust/crossbeam-channel/src/lib.rs b/third_party/rust/crossbeam-channel/src/lib.rs
new file mode 100644
index 0000000000..cc1ef112f9
--- /dev/null
+++ b/third_party/rust/crossbeam-channel/src/lib.rs
@@ -0,0 +1,371 @@
+//! Multi-producer multi-consumer channels for message passing.
+//!
+//! This crate is an alternative to [`std::sync::mpsc`] with more features and better performance.
+//!
+//! # Hello, world!
+//!
+//! ```
+//! use crossbeam_channel::unbounded;
+//!
+//! // Create a channel of unbounded capacity.
+//! let (s, r) = unbounded();
+//!
+//! // Send a message into the channel.
+//! s.send("Hello, world!").unwrap();
+//!
+//! // Receive the message from the channel.
+//! assert_eq!(r.recv(), Ok("Hello, world!"));
+//! ```
+//!
+//! # Channel types
+//!
+//! Channels can be created using two functions:
+//!
+//! * [`bounded`] creates a channel of bounded capacity, i.e. there is a limit to how many messages
+//! it can hold at a time.
+//!
+//! * [`unbounded`] creates a channel of unbounded capacity, i.e. it can hold any number of
+//! messages at a time.
+//!
+//! Both functions return a [`Sender`] and a [`Receiver`], which represent the two opposite sides
+//! of a channel.
+//!
+//! Creating a bounded channel:
+//!
+//! ```
+//! use crossbeam_channel::bounded;
+//!
+//! // Create a channel that can hold at most 5 messages at a time.
+//! let (s, r) = bounded(5);
+//!
+//! // Can send only 5 messages without blocking.
+//! for i in 0..5 {
+//! s.send(i).unwrap();
+//! }
+//!
+//! // Another call to `send` would block because the channel is full.
+//! // s.send(5).unwrap();
+//! ```
+//!
+//! Creating an unbounded channel:
+//!
+//! ```
+//! use crossbeam_channel::unbounded;
+//!
+//! // Create an unbounded channel.
+//! let (s, r) = unbounded();
+//!
+//! // Can send any number of messages into the channel without blocking.
+//! for i in 0..1000 {
+//! s.send(i).unwrap();
+//! }
+//! ```
+//!
+//! A special case is zero-capacity channel, which cannot hold any messages. Instead, send and
+//! receive operations must appear at the same time in order to pair up and pass the message over:
+//!
+//! ```
+//! use std::thread;
+//! use crossbeam_channel::bounded;
+//!
+//! // Create a zero-capacity channel.
+//! let (s, r) = bounded(0);
+//!
+//! // Sending blocks until a receive operation appears on the other side.
+//! thread::spawn(move || s.send("Hi!").unwrap());
+//!
+//! // Receiving blocks until a send operation appears on the other side.
+//! assert_eq!(r.recv(), Ok("Hi!"));
+//! ```
+//!
+//! # Sharing channels
+//!
+//! Senders and receivers can be cloned and sent to other threads:
+//!
+//! ```
+//! use std::thread;
+//! use crossbeam_channel::bounded;
+//!
+//! let (s1, r1) = bounded(0);
+//! let (s2, r2) = (s1.clone(), r1.clone());
+//!
+//! // Spawn a thread that receives a message and then sends one.
+//! thread::spawn(move || {
+//! r2.recv().unwrap();
+//! s2.send(2).unwrap();
+//! });
+//!
+//! // Send a message and then receive one.
+//! s1.send(1).unwrap();
+//! r1.recv().unwrap();
+//! ```
+//!
+//! Note that cloning only creates a new handle to the same sending or receiving side. It does not
+//! create a separate stream of messages in any way:
+//!
+//! ```
+//! use crossbeam_channel::unbounded;
+//!
+//! let (s1, r1) = unbounded();
+//! let (s2, r2) = (s1.clone(), r1.clone());
+//! let (s3, r3) = (s2.clone(), r2.clone());
+//!
+//! s1.send(10).unwrap();
+//! s2.send(20).unwrap();
+//! s3.send(30).unwrap();
+//!
+//! assert_eq!(r3.recv(), Ok(10));
+//! assert_eq!(r1.recv(), Ok(20));
+//! assert_eq!(r2.recv(), Ok(30));
+//! ```
+//!
+//! It's also possible to share senders and receivers by reference:
+//!
+//! ```
+//! use crossbeam_channel::bounded;
+//! use crossbeam_utils::thread::scope;
+//!
+//! let (s, r) = bounded(0);
+//!
+//! scope(|scope| {
+//! // Spawn a thread that receives a message and then sends one.
+//! scope.spawn(|_| {
+//! r.recv().unwrap();
+//! s.send(2).unwrap();
+//! });
+//!
+//! // Send a message and then receive one.
+//! s.send(1).unwrap();
+//! r.recv().unwrap();
+//! }).unwrap();
+//! ```
+//!
+//! # Disconnection
+//!
+//! When all senders or all receivers associated with a channel get dropped, the channel becomes
+//! disconnected. No more messages can be sent, but any remaining messages can still be received.
+//! Send and receive operations on a disconnected channel never block.
+//!
+//! ```
+//! use crossbeam_channel::{unbounded, RecvError};
+//!
+//! let (s, r) = unbounded();
+//! s.send(1).unwrap();
+//! s.send(2).unwrap();
+//! s.send(3).unwrap();
+//!
+//! // The only sender is dropped, disconnecting the channel.
+//! drop(s);
+//!
+//! // The remaining messages can be received.
+//! assert_eq!(r.recv(), Ok(1));
+//! assert_eq!(r.recv(), Ok(2));
+//! assert_eq!(r.recv(), Ok(3));
+//!
+//! // There are no more messages in the channel.
+//! assert!(r.is_empty());
+//!
+//! // Note that calling `r.recv()` does not block.
+//! // Instead, `Err(RecvError)` is returned immediately.
+//! assert_eq!(r.recv(), Err(RecvError));
+//! ```
+//!
+//! # Blocking operations
+//!
+//! Send and receive operations come in three flavors:
+//!
+//! * Non-blocking (returns immediately with success or failure).
+//! * Blocking (waits until the operation succeeds or the channel becomes disconnected).
+//! * Blocking with a timeout (blocks only for a certain duration of time).
+//!
+//! A simple example showing the difference between non-blocking and blocking operations:
+//!
+//! ```
+//! use crossbeam_channel::{bounded, RecvError, TryRecvError};
+//!
+//! let (s, r) = bounded(1);
+//!
+//! // Send a message into the channel.
+//! s.send("foo").unwrap();
+//!
+//! // This call would block because the channel is full.
+//! // s.send("bar").unwrap();
+//!
+//! // Receive the message.
+//! assert_eq!(r.recv(), Ok("foo"));
+//!
+//! // This call would block because the channel is empty.
+//! // r.recv();
+//!
+//! // Try receiving a message without blocking.
+//! assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
+//!
+//! // Disconnect the channel.
+//! drop(s);
+//!
+//! // This call doesn't block because the channel is now disconnected.
+//! assert_eq!(r.recv(), Err(RecvError));
+//! ```
+//!
+//! # Iteration
+//!
+//! Receivers can be used as iterators. For example, method [`iter`] creates an iterator that
+//! receives messages until the channel becomes empty and disconnected. Note that iteration may
+//! block waiting for next message to arrive.
+//!
+//! ```
+//! use std::thread;
+//! use crossbeam_channel::unbounded;
+//!
+//! let (s, r) = unbounded();
+//!
+//! thread::spawn(move || {
+//! s.send(1).unwrap();
+//! s.send(2).unwrap();
+//! s.send(3).unwrap();
+//! drop(s); // Disconnect the channel.
+//! });
+//!
+//! // Collect all messages from the channel.
+//! // Note that the call to `collect` blocks until the sender is dropped.
+//! let v: Vec<_> = r.iter().collect();
+//!
+//! assert_eq!(v, [1, 2, 3]);
+//! ```
+//!
+//! A non-blocking iterator can be created using [`try_iter`], which receives all available
+//! messages without blocking:
+//!
+//! ```
+//! use crossbeam_channel::unbounded;
+//!
+//! let (s, r) = unbounded();
+//! s.send(1).unwrap();
+//! s.send(2).unwrap();
+//! s.send(3).unwrap();
+//! // No need to drop the sender.
+//!
+//! // Receive all messages currently in the channel.
+//! let v: Vec<_> = r.try_iter().collect();
+//!
+//! assert_eq!(v, [1, 2, 3]);
+//! ```
+//!
+//! # Selection
+//!
+//! The [`select!`] macro allows you to define a set of channel operations, wait until any one of
+//! them becomes ready, and finally execute it. If multiple operations are ready at the same time,
+//! a random one among them is selected.
+//!
+//! It is also possible to define a `default` case that gets executed if none of the operations are
+//! ready, either right away or for a certain duration of time.
+//!
+//! An operation is considered to be ready if it doesn't have to block. Note that it is ready even
+//! when it will simply return an error because the channel is disconnected.
+//!
+//! An example of receiving a message from two channels:
+//!
+//! ```
+//! use std::thread;
+//! use std::time::Duration;
+//! use crossbeam_channel::{select, unbounded};
+//!
+//! let (s1, r1) = unbounded();
+//! let (s2, r2) = unbounded();
+//!
+//! thread::spawn(move || s1.send(10).unwrap());
+//! thread::spawn(move || s2.send(20).unwrap());
+//!
+//! // At most one of these two receive operations will be executed.
+//! select! {
+//! recv(r1) -> msg => assert_eq!(msg, Ok(10)),
+//! recv(r2) -> msg => assert_eq!(msg, Ok(20)),
+//! default(Duration::from_secs(1)) => println!("timed out"),
+//! }
+//! ```
+//!
+//! If you need to select over a dynamically created list of channel operations, use [`Select`]
+//! instead. The [`select!`] macro is just a convenience wrapper around [`Select`].
+//!
+//! # Extra channels
+//!
+//! Three functions can create special kinds of channels, all of which return just a [`Receiver`]
+//! handle:
+//!
+//! * [`after`] creates a channel that delivers a single message after a certain duration of time.
+//! * [`tick`] creates a channel that delivers messages periodically.
+//! * [`never`](never()) creates a channel that never delivers messages.
+//!
+//! These channels are very efficient because messages get lazily generated on receive operations.
+//!
+//! An example that prints elapsed time every 50 milliseconds for the duration of 1 second:
+//!
+//! ```
+//! use std::time::{Duration, Instant};
+//! use crossbeam_channel::{after, select, tick};
+//!
+//! let start = Instant::now();
+//! let ticker = tick(Duration::from_millis(50));
+//! let timeout = after(Duration::from_secs(1));
+//!
+//! loop {
+//! select! {
+//! recv(ticker) -> _ => println!("elapsed: {:?}", start.elapsed()),
+//! recv(timeout) -> _ => break,
+//! }
+//! }
+//! ```
+//!
+//! [`send`]: Sender::send
+//! [`recv`]: Receiver::recv
+//! [`iter`]: Receiver::iter
+//! [`try_iter`]: Receiver::try_iter
+
+#![doc(test(
+ no_crate_inject,
+ attr(
+ deny(warnings, rust_2018_idioms),
+ allow(dead_code, unused_assignments, unused_variables)
+ )
+))]
+#![warn(
+ missing_docs,
+ missing_debug_implementations,
+ rust_2018_idioms,
+ unreachable_pub
+)]
+#![cfg_attr(not(feature = "std"), no_std)]
+
+use cfg_if::cfg_if;
+
+cfg_if! {
+ if #[cfg(feature = "std")] {
+ mod channel;
+ mod context;
+ mod counter;
+ mod err;
+ mod flavors;
+ mod select;
+ mod select_macro;
+ mod utils;
+ mod waker;
+
+ /// Crate internals used by the `select!` macro.
+ #[doc(hidden)]
+ pub mod internal {
+ pub use crate::select::SelectHandle;
+ pub use crate::select::{select, select_timeout, try_select};
+ }
+
+ pub use crate::channel::{after, at, never, tick};
+ pub use crate::channel::{bounded, unbounded};
+ pub use crate::channel::{IntoIter, Iter, TryIter};
+ pub use crate::channel::{Receiver, Sender};
+
+ pub use crate::select::{Select, SelectedOperation};
+
+ pub use crate::err::{ReadyTimeoutError, SelectTimeoutError, TryReadyError, TrySelectError};
+ pub use crate::err::{RecvError, RecvTimeoutError, TryRecvError};
+ pub use crate::err::{SendError, SendTimeoutError, TrySendError};
+ }
+}