]> git.proxmox.com Git - cargo.git/blobdiff - vendor/crossbeam-channel/src/lib.rs
New upstream version 0.33.0
[cargo.git] / vendor / crossbeam-channel / src / lib.rs
index b4d54a63507267111d58b9f7ddf4a5ad2d8c1040..877378cea45a25bf4ef6d587078406766561eea7 100644 (file)
 //! Multi-producer multi-consumer channels for message passing.
 //!
-//! Crossbeam's channels are an alternative to the [`std::sync::mpsc`] channels provided by the
-//! standard library. They are an improvement in terms of performance, ergonomics, and features.
+//! This crate is an alternative to [`std::sync::mpsc`] with more features and better performance.
 //!
-//! Here's a quick example:
+//! # Hello, world!
 //!
 //! ```
-//! use crossbeam_channel as channel;
+//! use crossbeam_channel::unbounded;
 //!
 //! // Create a channel of unbounded capacity.
-//! let (s, r) = channel::unbounded();
+//! let (s, r) = unbounded();
 //!
 //! // Send a message into the channel.
-//! s.send("Hello world!");
+//! s.send("Hello, world!").unwrap();
 //!
 //! // Receive the message from the channel.
-//! assert_eq!(r.recv(), Some("Hello world!"));
+//! assert_eq!(r.recv(), Ok("Hello, world!"));
 //! ```
 //!
-//! # Types of channels
+//! # Channel types
 //!
-//! Channels are created using two functions:
+//! 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.
+//!   it can hold at a time.
 //!
-//! * [`unbounded`] creates a channel of unbounded capacity, i.e. it can contain arbitrary number
-//!   of messages at any time.
+//! * [`unbounded`] creates a channel of unbounded capacity, i.e. it can hold any number of
+//!   messages at a time.
 //!
-//! Both functions return two handles: a sender and a receiver. Senders and receivers represent
-//! two opposite sides of a channel. Messages are sent into the channel using senders and received
-//! using receivers.
+//! Both functions return a [`Sender`] and a [`Receiver`], which represent the two opposite sides
+//! of a channel.
 //!
 //! Creating a bounded channel:
 //!
 //! ```
-//! use crossbeam_channel as channel;
+//! use crossbeam_channel::bounded;
 //!
 //! // Create a channel that can hold at most 5 messages at a time.
-//! let (s, r) = channel::bounded(5);
+//! let (s, r) = bounded(5);
 //!
-//! // Can only send 5 messages without blocking.
+//! // Can send only 5 messages without blocking.
 //! for i in 0..5 {
-//!     s.send(i);
+//!     s.send(i).unwrap();
 //! }
 //!
 //! // Another call to `send` would block because the channel is full.
-//! // s.send(5);
+//! // s.send(5).unwrap();
 //! ```
 //!
 //! Creating an unbounded channel:
 //!
 //! ```
-//! use crossbeam_channel as channel;
+//! use crossbeam_channel::unbounded;
 //!
 //! // Create an unbounded channel.
-//! let (s, r) = channel::unbounded();
+//! let (s, r) = unbounded();
 //!
 //! // Can send any number of messages into the channel without blocking.
 //! for i in 0..1000 {
-//!     s.send(i);
+//!     s.send(i).unwrap();
 //! }
 //! ```
 //!
-//! A rather special case is a bounded, zero-capacity channel. This kind of channel cannot hold any
-//! messages at all! In order to send a message through the channel, a sending thread and a
-//! receiving thread have to pair up at the same time:
+//! 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 as channel;
+//! use crossbeam_channel::bounded;
 //!
 //! // Create a zero-capacity channel.
-//! let (s, r) = channel::bounded(0);
+//! let (s, r) = bounded(0);
 //!
-//! // Spawn a thread that sends a message into the channel.
 //! // Sending blocks until a receive operation appears on the other side.
-//! thread::spawn(move || s.send("Hi!"));
+//! thread::spawn(move || s.send("Hi!").unwrap());
 //!
-//! // Receive the message.
 //! // Receiving blocks until a send operation appears on the other side.
-//! assert_eq!(r.recv(), Some("Hi!"));
+//! assert_eq!(r.recv(), Ok("Hi!"));
 //! ```
 //!
 //! # Sharing channels
 //!
-//! Senders and receivers can be either shared by reference or cloned and then sent to other
-//! threads. There can be multiple senders and multiple receivers associated with the same channel.
-//!
-//! Sharing by reference:
+//! Senders and receivers can be cloned and sent to other threads:
 //!
 //! ```
-//! # extern crate crossbeam_channel;
-//! extern crate crossbeam;
-//! # fn main() {
-//! use crossbeam_channel as channel;
-//!
-//! let (s, r) = channel::unbounded();
+//! use std::thread;
+//! use crossbeam_channel::bounded;
 //!
-//! crossbeam::scope(|scope| {
-//!     // Spawn a thread that sends one message and then receives one.
-//!     scope.spawn(|| {
-//!         s.send(1);
-//!         r.recv().unwrap();
-//!     });
+//! let (s1, r1) = bounded(0);
+//! let (s2, r2) = (s1.clone(), r1.clone());
 //!
-//!     // Spawn another thread that does the same thing.
-//!     scope.spawn(|| {
-//!         s.send(2);
-//!         r.recv().unwrap();
-//!     });
+//! // 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();
 //! ```
 //!
-//! Sharing by cloning:
+//! 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 std::thread;
-//! use crossbeam_channel as channel;
+//! use crossbeam_channel::unbounded;
 //!
-//! let (s1, r1) = channel::unbounded();
+//! let (s1, r1) = unbounded();
 //! let (s2, r2) = (s1.clone(), r1.clone());
+//! let (s3, r3) = (s2.clone(), r2.clone());
 //!
-//! // Spawn a thread that sends one message and then receives one.
-//! thread::spawn(move || {
-//!     s1.send(1);
-//!     r1.recv().unwrap();
-//! });
+//! s1.send(10).unwrap();
+//! s2.send(20).unwrap();
+//! s3.send(30).unwrap();
 //!
-//! // Spawn another thread that receives a message and then sends one.
-//! thread::spawn(move || {
-//!     r2.recv().unwrap();
-//!     s2.send(2);
-//! });
+//! assert_eq!(r3.recv(), Ok(10));
+//! assert_eq!(r1.recv(), Ok(20));
+//! assert_eq!(r2.recv(), Ok(30));
 //! ```
 //!
-//! Note that cloning only creates a new reference to the same sending or receiving side. Cloning
-//! does not create a new channel.
+//! It's also possible to share senders and receivers by reference:
+//!
+//! ```
+//! # extern crate crossbeam_channel;
+//! # extern crate crossbeam_utils;
+//! # fn main() {
+//! use std::thread;
+//! 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();
+//! # }
+//! ```
 //!
-//! # Closing channels
+//! # Disconnection
 //!
-//! When all senders associated with a channel get dropped, the channel becomes closed. No more
-//! messages can be sent, but any remaining messages can still be received. Receive operations on a
-//! closed channel never block, even if the channel is empty.
+//! 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 as channel;
+//! use crossbeam_channel::{unbounded, RecvError};
 //!
-//! let (s, r) = channel::unbounded();
-//! s.send(1);
-//! s.send(2);
-//! s.send(3);
+//! let (s, r) = unbounded();
+//! s.send(1).unwrap();
+//! s.send(2).unwrap();
+//! s.send(3).unwrap();
 //!
-//! // The only sender is dropped, closing the channel.
+//! // The only sender is dropped, disconnecting the channel.
 //! drop(s);
 //!
 //! // The remaining messages can be received.
-//! assert_eq!(r.recv(), Some(1));
-//! assert_eq!(r.recv(), Some(2));
-//! assert_eq!(r.recv(), Some(3));
+//! 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()` will not block.
-//! // Instead, `None` is returned immediately.
-//! assert_eq!(r.recv(), None);
+//! // Note that calling `r.recv()` does not block.
+//! // Instead, `Err(RecvError)` is returned immediately.
+//! assert_eq!(r.recv(), Err(RecvError));
 //! ```
 //!
-//! # Blocking and non-blocking operations
+//! # Blocking operations
 //!
-//! Sending a message into a full bounded channel will block until an empty slot in the channel
-//! becomes available. Sending into an unbounded channel never blocks because there is always
-//! enough space in it. Zero-capacity channels are always empty, and sending blocks until a receive
-//! operation appears on the other side of the channel.
+//! Send and receive operations come in three flavors:
 //!
-//! Receiving from an empty channel blocks until a message is sent into the channel or the channel
-//! becomes closed. Zero-capacity channels are always empty, and receiving blocks until a send
-//! operation appears on the other side of the channel or it becomes closed.
+//! * 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).
 //!
-//! There is also a non-blocking method [`try_recv`], which receives a message if it is immediately
-//! available, or returns `None` otherwise.
+//! A simple example showing the difference between non-blocking and blocking operations:
 //!
 //! ```
-//! use crossbeam_channel as channel;
+//! use crossbeam_channel::{bounded, RecvError, TryRecvError};
 //!
-//! let (s, r) = channel::bounded(1);
+//! let (s, r) = bounded(1);
 //!
 //! // Send a message into the channel.
-//! s.send("foo");
+//! s.send("foo").unwrap();
 //!
 //! // This call would block because the channel is full.
-//! // s.send("bar");
+//! // s.send("bar").unwrap();
 //!
 //! // Receive the message.
-//! assert_eq!(r.recv(), Some("foo"));
+//! 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(), None);
+//! assert_eq!(r.try_recv(), Err(TryRecvError::Empty));
 //!
-//! // Close the channel.
+//! // Disconnect the channel.
 //! drop(s);
 //!
-//! // This call doesn't block because the channel is now closed.
-//! assert_eq!(r.recv(), None);
+//! // This call doesn't block because the channel is now disconnected.
+//! assert_eq!(r.recv(), Err(RecvError));
 //! ```
 //!
-//! For greater control over blocking, consider using the [`select!`] macro.
-//!
 //! # Iteration
 //!
-//! A channel is a special kind of iterator, where items can be dynamically produced by senders and
-//! consumed by receivers. Indeed, [`Receiver`] implements the [`Iterator`] trait, and calling
-//! [`next`] is equivalent to calling [`recv`].
+//! 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 as channel;
+//! use crossbeam_channel::unbounded;
 //!
-//! let (s, r) = channel::unbounded();
+//! let (s, r) = unbounded();
 //!
 //! thread::spawn(move || {
-//!     s.send(1);
-//!     s.send(2);
-//!     s.send(3);
-//!     // `s` was moved into the closure so now it gets dropped,
-//!     // thus closing the channel.
+//!     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 channel becomes
-//! // closed and empty, i.e. until `r.next()` returns `None`.
-//! let v: Vec<_> = r.collect();
+//! // Note that the call to `collect` blocks until the sender is dropped.
+//! let v: Vec<_> = r.iter().collect();
+//!
 //! assert_eq!(v, [1, 2, 3]);
 //! ```
 //!
-//! # Select
-//!
-//! The [`select!`] macro allows declaring a set of channel operations and blocking until any one
-//! of them becomes ready. Finally, one of the operations is executed. If multiple operations
-//! are ready at the same time, a random one is chosen. It is also possible to declare a `default`
-//! case that gets executed if none of the operations are initially ready.
-//!
-//! An example of receiving a message from two channels, whichever becomes ready first:
+//! A non-blocking iterator can be created using [`try_iter`], which receives all available
+//! messages without blocking:
 //!
 //! ```
-//! # #[macro_use]
-//! # extern crate crossbeam_channel;
-//! # fn main() {
-//! use std::thread;
-//! use crossbeam_channel as channel;
+//! use crossbeam_channel::unbounded;
 //!
-//! let (s1, r1) = channel::unbounded();
-//! let (s2, r2) = channel::unbounded();
+//! let (s, r) = unbounded();
+//! s.send(1).unwrap();
+//! s.send(2).unwrap();
+//! s.send(3).unwrap();
+//! // No need to drop the sender.
 //!
-//! thread::spawn(move || s1.send("foo"));
-//! thread::spawn(move || s2.send("bar"));
+//! // Receive all messages currently in the channel.
+//! let v: Vec<_> = r.try_iter().collect();
 //!
-//! // Only one of these two receive operations will be executed.
-//! select! {
-//!     recv(r1, msg) => assert_eq!(msg, Some("foo")),
-//!     recv(r2, msg) => assert_eq!(msg, Some("bar")),
-//! }
-//! # }
+//! assert_eq!(v, [1, 2, 3]);
 //! ```
 //!
-//! For more details, take a look at the documentation for [`select!`].
+//! # Selection
 //!
-//! If you need to dynamically add cases rather than define them statically inside the macro, use
-//! [`Select`] instead.
+//! 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.
 //!
-//! # Frequently asked questions
+//! 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.
 //!
-//! ### How to try receiving a message, but also check whether the channel is empty or closed?
+//! 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.
 //!
-//! Use the [`select!`] macro:
+//! An example of receiving a message from two channels:
 //!
-//! ```rust
+//! ```
 //! # #[macro_use]
 //! # extern crate crossbeam_channel;
 //! # fn main() {
-//! use crossbeam_channel as channel;
+//! use std::thread;
+//! use std::time::Duration;
+//! use crossbeam_channel::unbounded;
+//!
+//! let (s1, r1) = unbounded();
+//! let (s2, r2) = unbounded();
 //!
-//! let (s, r) = channel::unbounded();
-//! s.send("hello");
+//! 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(r, msg) => match msg {
-//!         Some(msg) => println!("received {:?}", msg),
-//!         None => println!("the channel is closed"),
-//!     }
-//!     default => println!("the channel is empty"),
+//!     recv(r1) -> msg => assert_eq!(msg, Ok(10)),
+//!     recv(r2) -> msg => assert_eq!(msg, Ok(20)),
+//!     default(Duration::from_secs(1)) => println!("timed out"),
 //! }
 //! # }
 //! ```
 //!
-//! ### How to try sending a message without blocking when the channel is full?
-//!
-//! Use the [`select!`] macro:
-//!
-//! ```rust
-//! # #[macro_use]
-//! # extern crate crossbeam_channel;
-//! # fn main() {
-//! use crossbeam_channel as channel;
+//! 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`].
 //!
-//! let (s, r) = channel::bounded(1);
-//! s.send("first");
+//! # Extra channels
 //!
-//! select! {
-//!     send(s, "second") => println!("message sent"),
-//!     default => println!("the channel is full"),
-//! }
-//! # }
-//! ```
+//! Three functions can create special kinds of channels, all of which return just a [`Receiver`]
+//! handle:
 //!
-//! ### How to try sending/receiving a message with a timeout?
+//! * [`after`] creates a channel that delivers a single message after a certain duration of time.
+//! * [`tick`] creates a channel that delivers messages periodically.
+//! * [`never`] creates a channel that never delivers messages.
 //!
-//! Function [`after`] creates a special kind of channel that delivers a message after the
-//! specified timeout. Use [`select!`] to wait until a message is sent/received or the timeout
-//! is fired:
+//! 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:
 //!
-//! ```rust
+//! ```
 //! # #[macro_use]
 //! # extern crate crossbeam_channel;
 //! # fn main() {
-//! use std::time::Duration;
-//! use crossbeam_channel as channel;
+//! use std::time::{Duration, Instant};
+//! use crossbeam_channel::{after, tick};
 //!
-//! let (s, r) = channel::bounded(1);
-//! s.send("hello");
+//! let start = Instant::now();
+//! let ticker = tick(Duration::from_millis(50));
+//! let timeout = after(Duration::from_secs(1));
 //!
-//! let timeout = Duration::from_millis(100);
-//!
-//! select! {
-//!     recv(r, msg) => match msg {
-//!         Some(msg) => println!("received {:?}", msg),
-//!         None => println!("the channel is closed"),
+//! loop {
+//!     select! {
+//!         recv(ticker) -> _ => println!("elapsed: {:?}", start.elapsed()),
+//!         recv(timeout) -> _ => break,
 //!     }
-//!     recv(channel::after(timeout)) => println!("timed out; the channel is still empty"),
 //! }
 //! # }
 //! ```
 //! [`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html
 //! [`unbounded`]: fn.unbounded.html
 //! [`bounded`]: fn.bounded.html
-//! [`after`]: fn.bounded.html
+//! [`after`]: fn.after.html
+//! [`tick`]: fn.tick.html
+//! [`never`]: fn.never.html
 //! [`send`]: struct.Sender.html#method.send
-//! [`try_recv`]: struct.Receiver.html#method.try_recv
 //! [`recv`]: struct.Receiver.html#method.recv
-//! [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
-//! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
+//! [`iter`]: struct.Receiver.html#method.iter
+//! [`try_iter`]: struct.Receiver.html#method.try_iter
 //! [`select!`]: macro.select.html
 //! [`Select`]: struct.Select.html
 //! [`Sender`]: struct.Sender.html
 //! [`Receiver`]: struct.Receiver.html
 
-extern crate crossbeam_epoch;
+#![warn(missing_docs)]
+#![warn(missing_debug_implementations)]
+
 extern crate crossbeam_utils;
-extern crate rand;
-extern crate parking_lot;
+extern crate smallvec;
 
+mod channel;
+mod context;
+mod counter;
+mod err;
 mod flavors;
+mod select;
+mod select_macro;
+mod utils;
+mod waker;
+
+pub use channel::{after, never, tick};
+pub use channel::{bounded, unbounded};
+pub use channel::{IntoIter, Iter, TryIter};
+pub use channel::{Receiver, Sender};
 
-#[doc(hidden)]
-pub mod internal;
+pub use select::{Select, SelectedOperation};
 
-pub use internal::channel::{Receiver, Sender};
-pub use internal::channel::{bounded, unbounded};
-pub use internal::channel::{after, tick};
-pub use internal::select::Select;
+pub use err::{RecvError, RecvTimeoutError, TryRecvError};
+pub use err::{ReadyTimeoutError, SelectTimeoutError, TryReadyError, TrySelectError};
+pub use err::{SendError, SendTimeoutError, TrySendError};