### Create Bounded and Rendezvous Channels Source: https://context7.com/zesterer/flume/llms.txt Shows how to create a bounded channel with a specific capacity and a rendezvous channel (capacity 0). Demonstrates blocking behavior on full bounded channels and direct synchronization for rendezvous channels. ```rust use std::thread; use std::time::Duration; fn main() { // Bounded channel with capacity 2 let (tx, rx) = flume::bounded::<&str>(2); tx.send("first").unwrap(); tx.send("second").unwrap(); // Channel is now full – try_send returns Err immediately assert!(tx.try_send("third").is_err()); // Spawn a consumer to drain one slot thread::spawn(move || { thread::sleep(Duration::from_millis(10)); println!("Consumed: {}", rx.recv().unwrap()); // "first" println!("Consumed: {}", rx.recv().unwrap()); // "second" println!("Consumed: {}", rx.recv().unwrap()); // "third" (after send unblocks) }); // This blocks until the consumer reads "first" tx.send("third").unwrap(); thread::sleep(Duration::from_millis(50)); // --- Rendezvous (capacity 0) --- let (rtx, rrx) = flume::bounded::(0); thread::spawn(move || { // Blocks until a receiver is ready rtx.send(99).unwrap(); println!("Handshake complete"); }); assert_eq!(rrx.recv().unwrap(), 99); } ``` -------------------------------- ### Basic Unbounded Channel Usage in Rust Source: https://github.com/zesterer/flume/blob/master/README.md Demonstrates the creation and usage of an unbounded channel for sending and receiving integers between threads. Ensure the `flume` crate is added to your `Cargo.toml`. ```rust use std::thread; fn main() { println!("Hello, world!"); let (tx, rx) = flume::unbounded(); thread::spawn(move || { (0..10).for_each(|i| { tx.send(i).unwrap(); }) }); let received: u32 = rx.iter().sum(); assert_eq!((0..10).sum::(), received); } ``` -------------------------------- ### Create Unbounded Channel with Multiple Producers Source: https://context7.com/zesterer/flume/llms.txt Demonstrates creating an unbounded channel and using cloned senders for multiple producers. Receivers can collect messages using `try_iter`. ```rust use std::thread; fn main() { let (tx, rx) = flume::unbounded::(); // Clone sender for multiple producers let tx2 = tx.clone(); let producer1 = thread::spawn(move || { for i in 0..5 { tx.send(i).unwrap(); } }); let producer2 = thread::spawn(move || { for i in 5..10 { tx2.send(i).unwrap(); } }); producer1.join().unwrap(); producer2.join().unwrap(); // Collect all 10 messages let mut msgs: Vec = rx.try_iter().collect(); msgs.sort(); assert_eq!(msgs, (0..10).collect::>()); println!("Received: {:?}", msgs); // Output: Received: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] } ``` -------------------------------- ### Enabling Flume Cargo Features Source: https://github.com/zesterer/flume/blob/master/README.md Customize Flume's functionality by enabling specific features like `async` and `select` in your `Cargo.toml`. Set `default-features = false` to disable all default features before enabling specific ones. ```toml flume = { version = "x.y", default-features = false, features = ["async", "select"] } ``` -------------------------------- ### Selector — Wait on multiple channels Source: https://context7.com/zesterer/flume/llms.txt Allows a thread to register multiple send/receive operations and blocks until exactly one completes. Supports eventual fairness for random selection among ready operations. Requires the 'select' feature. ```APIDOC ## `Selector` — Wait on multiple channels (`select` feature) Feature-gated (`select` feature). `Selector::new()` lets a thread register multiple send/receive operations and blocks until exactly one completes. With `eventual-fairness` enabled, the completed operation is chosen randomly among all ready ones to prevent starvation. ### Usage Example (Receive and Shutdown) ```rust // Cargo.toml: flume = { version = "0.12", features = ["select", "eventual-fairness"] } use flume::{Selector, SelectError}; use std::time::Duration; fn main() { let (tx_work, rx_work) = flume::unbounded::(); let (tx_shutdown, rx_shutdown) = flume::bounded::<()>(1); // Simulate work arriving std::thread::spawn(move || { tx_work.send("task-1".into()).unwrap(); tx_work.send("task-2".into()).unwrap(); }); // Event loop: handle work or shutdown loop { let action = Selector::new() .recv(&rx_work, |r| match r { Ok(task) => format!("work:{}", task), Err(_) => "work-channel-closed".into(), }) .recv(&rx_shutdown, |_| "shutdown".into()) .wait_timeout(Duration::from_millis(100)); match action { Ok(msg) if msg == "shutdown" => { println!("Shutting down"); break; } Ok(msg) if msg.starts_with("work-channel-closed") => { println!("No more work"); break; } Ok(msg) => println!("Handling: {}", msg), Err(SelectError::Timeout) => { println!("Idle tick"); break; } } } // Output (order may vary): // Handling: work:task-1 // Handling: work:task-2 // Idle tick (or "No more work" depending on timing) } ``` ### Usage Example (Send) ```rust // Selector with a send operation let (tx2, rx2) = flume::bounded::(1); let result = Selector::new() .send(&tx2, 42, |r| r.is_ok()) .wait(); assert!(result); assert_eq!(rx2.recv().unwrap(), 42); ``` ``` -------------------------------- ### Sender::send_async / Receiver::recv_async Source: https://context7.com/zesterer/flume/llms.txt Provides `Future`-returning methods for asynchronous sending and receiving. These methods yield to the async runtime when the channel is full (send) or empty (recv). ```APIDOC ## Sender::send_async / Receiver::recv_async — Async send and receive ### Description Feature-gated (`async` feature). Provides `Future`-returning methods that yield to the async runtime when the channel is full (send) or empty (recv). Work with any runtime. ### Methods - `send_async(item: T) -> impl Future>>`: Asynchronously sends an item. - `recv_async() -> impl Future>`: Asynchronously receives an item. ### Example ```rust // Cargo.toml: flume = { version = "0.12", features = ["async"] } #[tokio::main] async fn main() { let (tx, rx) = flume::bounded::(2); // Async producer let producer = tokio::spawn(async move { tx.send_async("hello".into()).await.unwrap(); tx.send_async("world".into()).await.unwrap(); // tx dropped here, closing channel }); // Async consumer let consumer = tokio::spawn(async move { while let Ok(msg) = rx.recv_async().await { println!("Received: {}", msg); } println!("Channel closed"); }); producer.await.unwrap(); consumer.await.unwrap(); // Output: // Received: hello // Received: world // Channel closed } ``` ``` -------------------------------- ### Async Stream Adapter for Flume Receiver Source: https://context7.com/zesterer/flume/llms.txt Wraps a `Receiver` as a `futures::Stream` for use with `async for` and stream combinators. Requires the `async` feature flag. ```rust use futures::StreamExt; #[tokio::main] async fn main() { let (tx, rx) = flume::unbounded(); let mut stream = rx.into_stream(); tokio::spawn(async move { for i in 0..3u32 { tx.send(i).unwrap(); } // tx dropped – stream ends }); while let Some(val) = stream.next().await { println!("Stream item: {}", val); } // Output: // Stream item: 0 // Stream item: 1 // Stream item: 2 } ``` -------------------------------- ### Blocking Send on Bounded Channel Source: https://context7.com/zesterer/flume/llms.txt Illustrates the blocking behavior of `Sender::send` on a bounded channel. The sender will pause execution when the channel is full until a receiver consumes a message. ```rust use std::thread; fn main() { let (tx, rx) = flume::bounded(1); let t = thread::spawn(move || { // Blocks here until the receiver reads the first message tx.send("msg1").unwrap(); tx.send("msg2").unwrap(); println!("All messages sent"); }); thread::sleep(std::time::Duration::from_millis(5)); assert_eq!(rx.recv().unwrap(), "msg1"); assert_eq!(rx.recv().unwrap(), "msg2"); t.join().unwrap(); } ``` -------------------------------- ### Send with Timeout/Deadline Source: https://context7.com/zesterer/flume/llms.txt Use `send_timeout` or `send_deadline` to send messages with a time limit. Returns `Err(SendTimeoutError::Timeout)` if the time expires before space is available. ```rust use flume::SendTimeoutError; use std::time::{Duration, Instant}; fn main() { let (tx, _rx) = flume::bounded::<&str>(0); // rendezvous – always full without a receiver // Timeout variant match tx.send_timeout("hello", Duration::from_millis(50)) { Err(SendTimeoutError::Timeout(msg)) => println!("Timed out sending: {}", msg), Err(SendTimeoutError::Disconnected(msg)) => println!("Disconnected: {}", msg), Ok(()) => println!("Sent"), } // Output: Timed out sending: hello // Deadline variant let deadline = Instant::now() + Duration::from_millis(50); match tx.send_deadline("world", deadline) { Err(SendTimeoutError::Timeout(msg)) => println!("Deadline passed: {}", msg), _ => {} } // Output: Deadline passed: world } ``` -------------------------------- ### Receiver::stream / Receiver::into_stream Source: https://context7.com/zesterer/flume/llms.txt Wraps a Receiver as a futures::Stream, enabling usage with stream combinators and async for loops. Requires the 'async' feature. ```APIDOC ## Receiver::stream / Receiver::into_stream — Async `Stream` adapter Feature-gated (`async` feature). Wraps a `Receiver` as a `futures::Stream`, allowing use with stream combinators and `async for` patterns. ### Usage Example ```rust // Cargo.toml: flume = { version = "0.12", features = ["async"] } use futures::StreamExt; #[tokio::main] async fn main() { let (tx, rx) = flume::unbounded(); let mut stream = rx.into_stream(); tokio::spawn(async move { for i in 0..3u32 { tx.send(i).unwrap(); } // tx dropped – stream ends }); while let Some(val) = stream.next().await { println!("Stream item: {}", val); } // Output: // Stream item: 0 // Stream item: 1 // Stream item: 2 } ``` ``` -------------------------------- ### Sender::sink / Sender::into_sink Source: https://context7.com/zesterer/flume/llms.txt Wraps a `Sender` as a `futures::Sink`, enabling use with sink combinators like `SinkExt::send_all`. ```APIDOC ## Sender::sink / Sender::into_sink — Async `Sink` adapter ### Description Feature-gated (`async` feature). Wraps a `Sender` as a `futures::Sink`, enabling use with sink combinators like `SinkExt::send_all`. ### Methods - `sink()`: Returns a `Sink` adapter for the sender. - `into_sink()`: Consumes the sender and returns a `Sink` adapter. ### Example ```rust // Cargo.toml: flume = { version = "0.12", features = ["async"] } use futures::SinkExt; use futures::StreamExt; #[tokio::main] async fn main() { let (tx, rx) = flume::bounded::(10); let mut sink = tx.into_sink(); // Use SinkExt combinators sink.send(1).await.unwrap(); sink.send(2).await.unwrap(); sink.send(3).await.unwrap(); drop(sink); // closes the channel let sum: i32 = rx.into_stream().fold(0, |acc, x| async move { acc + x }).await; assert_eq!(sum, 6); println!("Sum via Sink+Stream: {}", sum); // Output: Sum via Sink+Stream: 6 } ``` ``` -------------------------------- ### Sender::downgrade / WeakSender::upgrade Source: https://context7.com/zesterer/flume/llms.txt Manages weak references to a sender. `WeakSender` does not keep the channel open. It must be upgraded to a strong `Sender` before sending. ```APIDOC ## Sender::downgrade / WeakSender::upgrade — Weak sender ### Description `WeakSender` does not keep the channel open. When all strong `Sender`s are dropped the channel closes, regardless of live `WeakSender`s. Must be upgraded before sending. ### Methods - `downgrade()`: Creates a `WeakSender` from a `Sender`. - `upgrade()`: Attempts to upgrade a `WeakSender` to a `Sender`. ### Example ```rust let (tx, rx) = flume::unbounded::<&str>(); let weak = tx.downgrade(); // Can upgrade while a strong Sender exists if let Some(strong) = weak.upgrade() { strong.send("via weak upgrade").unwrap(); } assert_eq!(rx.recv().unwrap(), "via weak upgrade"); // Drop all strong senders drop(tx); // Upgrade fails – channel is closed assert!(weak.upgrade().is_none()); println!("Upgrade after drop: None"); // Output: Upgrade after drop: None ``` ``` -------------------------------- ### Sender::sink / Sender::into_sink — Async `Sink` adapter Source: https://context7.com/zesterer/flume/llms.txt Feature-gated (`async` feature). Wraps a `Sender` as a `futures::Sink`, enabling use with sink combinators like `SinkExt::send_all`. ```rust // Cargo.toml: flume = { version = "0.12", features = ["async"] } use futures::SinkExt; use futures::StreamExt; #[tokio::main] async fn main() { let (tx, rx) = flume::bounded::(10); let mut sink = tx.into_sink(); // Use SinkExt combinators sink.send(1).await.unwrap(); sink.send(2).await.unwrap(); sink.send(3).await.unwrap(); drop(sink); // closes the channel let sum: i32 = rx.into_stream().fold(0, |acc, x| async move { acc + x }).await; assert_eq!(sum, 6); println!("Sum via Sink+Stream: {}", sum); // Output: Sum via Sink+Stream: 6 } ``` -------------------------------- ### Flume Cargo Feature Flags Source: https://context7.com/zesterer/flume/llms.txt Lists available feature flags for Flume, including default, minimal, async, select, eventual-fairness, and spinlock options. ```toml # Full features (default) flume = "0.12" # Minimal (sync only, no async, no select) flume = { version = "0.12", default-features = false } # Async support only flume = { version = "0.12", default-features = false, features = ["async"] } # Select support with fairness flume = { version = "0.12", default-features = false, features = ["select", "eventual-fairness"] } # Spinlock internals (may improve performance on specific workloads) flume = { version = "0.12", default-features = false, features = ["spin"] } ``` -------------------------------- ### Adding Flume to Cargo.toml Source: https://github.com/zesterer/flume/blob/master/README.md To use Flume in your Rust project, add the following line to the `[dependencies]` section of your `Cargo.toml` file. ```toml flume = "x.y" ``` -------------------------------- ### Non-blocking Send with try_send Source: https://context7.com/zesterer/flume/llms.txt Demonstrates `Sender::try_send` for attempting to send a message without blocking. It returns an error if the channel is full (`TrySendError::Full`) or disconnected (`TrySendError::Disconnected`). ```rust use flume::TrySendError; fn main() { let (tx, rx) = flume::bounded::(2); assert!(tx.try_send(1).is_ok()); assert!(tx.try_send(2).is_ok()); match tx.try_send(3) { Err(TrySendError::Full(val)) => println!("Channel full, could not send {}", val), Err(TrySendError::Disconnected(val)) => println!("No receivers, dropped {}", val), Ok(()) => println!("Sent"), } // Output: Channel full, could not send 3 drop(rx); // drop all receivers match tx.try_send(4) { Err(TrySendError::Disconnected(val)) => println!("Disconnected, dropped {}", val), _ => {} } // Output: Disconnected, dropped 4 } ``` -------------------------------- ### Sender::downgrade / WeakSender::upgrade — Weak sender Source: https://context7.com/zesterer/flume/llms.txt `WeakSender` does not keep the channel open. When all strong `Sender`s are dropped the channel closes, regardless of live `WeakSender`s. Must be upgraded before sending. ```rust fn main() { let (tx, rx) = flume::unbounded::<&str>(); let weak = tx.downgrade(); // Can upgrade while a strong Sender exists if let Some(strong) = weak.upgrade() { strong.send("via weak upgrade").unwrap(); } assert_eq!(rx.recv().unwrap(), "via weak upgrade"); // Drop all strong senders drop(tx); // Upgrade fails – channel is closed assert!(weak.upgrade().is_none()); println!("Upgrade after drop: None"); // Output: Upgrade after drop: None } ``` -------------------------------- ### Multi-Channel Selection with Flume Selector Source: https://context7.com/zesterer/flume/llms.txt Blocks until one of multiple registered send/receive operations completes. Use with the `select` feature flag. `eventual-fairness` enables randomized selection. ```rust use flume::{Selector, SelectError}; use std::time::Duration; fn main() { let (tx_work, rx_work) = flume::unbounded::(); let (tx_shutdown, rx_shutdown) = flume::bounded::<()>(1); // Simulate work arriving std::thread::spawn(move || { tx_work.send("task-1".into()).unwrap(); tx_work.send("task-2".into()).unwrap(); }); // Event loop: handle work or shutdown loop { let action = Selector::new() .recv(&rx_work, |r| match r { Ok(task) => format!("work:{}", task), Err(_) => "work-channel-closed".into(), }) .recv(&rx_shutdown, |_| "shutdown".into()) .wait_timeout(Duration::from_millis(100)); match action { Ok(msg) if msg == "shutdown" => { println!("Shutting down"); break; } Ok(msg) if msg.starts_with("work-channel-closed") => { println!("No more work"); break; } Ok(msg) => println!("Handling: {}", msg), Err(SelectError::Timeout) => { println!("Idle tick"); break; } } } // Output (order may vary): // Handling: work:task-1 // Handling: work:task-2 // Idle tick (or "No more work" depending on timing) // Selector with a send operation let (tx2, rx2) = flume::bounded::(1); let result = Selector::new() .send(&tx2, 42, |r| r.is_ok()) .wait(); assert!(result); assert_eq!(rx2.recv().unwrap(), 42); } ``` -------------------------------- ### Sender::send_async / Receiver::recv_async — Async send and receive Source: https://context7.com/zesterer/flume/llms.txt Feature-gated (`async` feature). Provides `Future`-returning methods that yield to the async runtime when the channel is full (send) or empty (recv). Work with any runtime. ```rust // Cargo.toml: flume = { version = "0.12", features = ["async"] } #[tokio::main] async fn main() { let (tx, rx) = flume::bounded::(2); // Async producer let producer = tokio::spawn(async move { tx.send_async("hello".into()).await.unwrap(); tx.send_async("world".into()).await.unwrap(); // tx dropped here, closing channel }); // Async consumer let consumer = tokio::spawn(async move { while let Ok(msg) = rx.recv_async().await { println!("Received: {}", msg); } println!("Channel closed"); }); producer.await.unwrap(); consumer.await.unwrap(); // Output: // Received: hello // Received: world // Channel closed } ``` -------------------------------- ### Receive with Timeout/Deadline Source: https://context7.com/zesterer/flume/llms.txt Use `recv_timeout` or `recv_deadline` to wait for a message with a time limit. Returns `Err(RecvTimeoutError::Timeout)` if the time expires before a message is received. ```rust use flume::RecvTimeoutError; use std::time::{Duration, Instant}; fn main() { let (_tx, rx) = flume::unbounded::(); // Timeout variant – no sender ever sends match rx.recv_timeout(Duration::from_millis(50)) { Err(RecvTimeoutError::Timeout) => println!("Timed out waiting"), Err(RecvTimeoutError::Disconnected) => println!("Disconnected"), Ok(v) => println!("Got: {}", v), } // Output: Timed out waiting // Deadline variant let (tx2, rx2) = flume::unbounded(); let deadline = Instant::now() + Duration::from_secs(1); std::thread::spawn(move || { std::thread::sleep(Duration::from_millis(10)); tx2.send("on time").unwrap(); }); match rx2.recv_deadline(deadline) { Ok(v) => println!("Got: {}", v), Err(RecvTimeoutError::Timeout) => println!("Too slow"), Err(RecvTimeoutError::Disconnected) => println!("Disconnected"), } // Output: Got: on time } ``` -------------------------------- ### Flume Feature Descriptions Source: https://context7.com/zesterer/flume/llms.txt Provides descriptions for Flume's Cargo feature flags, detailing their functionality and dependencies. ```markdown | Feature | |---| | `async` | Enables `send_async`, `recv_async`, `sink`, `stream` APIs. Requires `futures-sink` and `futures-core`. | | `select` | Enables `Selector` for waiting on multiple channel operations. | | `eventual-fairness` | Adds randomised selection in `Selector` (implies `select`). Uses `fastrand`. | | `spin` | Uses spinlocks instead of OS-level synchronisation primitives internally. | ``` -------------------------------- ### Sender::sender_count / Receiver::receiver_count — Endpoint counts Source: https://context7.com/zesterer/flume/llms.txt Queries the number of currently live senders or receivers on the shared channel. ```rust fn main() { let (tx, rx) = flume::unbounded::<()>(); let tx2 = tx.clone(); let rx2 = rx.clone(); assert_eq!(tx.sender_count(), 2); // tx + tx2 assert_eq!(rx.receiver_count(), 2); // rx + rx2 drop(tx2); assert_eq!(tx.sender_count(), 1); drop(rx2); assert_eq!(rx.receiver_count(), 1); println!("Counts verified"); } ``` -------------------------------- ### flume::bounded Source: https://context7.com/zesterer/flume/llms.txt Creates a bounded channel with a fixed capacity. `Sender::send` blocks when the channel is full until space becomes available or all receivers are dropped. A capacity of 0 creates a rendezvous channel. ```APIDOC ## flume::bounded — Create a bounded channel ### Description Creates a channel with a fixed capacity. `Sender::send` blocks when the channel is full until space is available or all receivers are dropped. A capacity of `0` creates a rendezvous channel that synchronises sender and receiver directly. ### Usage Example ```rust use std::thread; use std::time::Duration; fn main() { // Bounded channel with capacity 2 let (tx, rx) = flume::bounded::<&str>(2); tx.send("first").unwrap(); tx.send("second").unwrap(); // Channel is now full – try_send returns Err immediately assert!(tx.try_send("third").is_err()); // Spawn a consumer to drain one slot thread::spawn(move || { thread::sleep(Duration::from_millis(10)); println!("Consumed: {}", rx.recv().unwrap()); // "first" println!("Consumed: {}", rx.recv().unwrap()); // "second" println!("Consumed: {}", rx.recv().unwrap()); // "third" (after send unblocks) }); // This blocks until the consumer reads "first" tx.send("third").unwrap(); thread::sleep(Duration::from_millis(50)); // --- Rendezvous (capacity 0) --- let (rtx, rrx) = flume::bounded::(0); thread::spawn(move || { // Blocks until a receiver is ready rtx.send(99).unwrap(); println!("Handshake complete"); }); assert_eq!(rrx.recv().unwrap(), 99); } ``` ``` -------------------------------- ### Sender::sender_count / Receiver::receiver_count Source: https://context7.com/zesterer/flume/llms.txt Queries the number of currently live senders or receivers on the shared channel. ```APIDOC ## Sender::sender_count / Receiver::receiver_count — Endpoint counts ### Description Queries the number of currently live senders or receivers on the shared channel. ### Methods - `sender_count()`: Returns the number of live senders. - `receiver_count()`: Returns the number of live receivers. ### Example ```rust let (tx, rx) = flume::unbounded::<()>(); let tx2 = tx.clone(); let rx2 = rx.clone(); assert_eq!(tx.sender_count(), 2); // tx + tx2 assert_eq!(rx.receiver_count(), 2); // rx + rx2 drop(tx2); assert_eq!(tx.sender_count(), 1); drop(rx2); assert_eq!(rx.receiver_count(), 1); println!("Counts verified"); ``` ``` -------------------------------- ### Non-blocking Receive Source: https://context7.com/zesterer/flume/llms.txt Use `Receiver::try_recv` for a non-blocking attempt to receive a message. Returns `Err(TryRecvError::Empty)` if no message is ready, or `Err(TryRecvError::Disconnected)` if the channel is closed and empty. ```rust use flume::TryRecvError; fn main() { let (tx, rx) = flume::unbounded(); tx.send("immediate").unwrap(); // Message is available assert_eq!(rx.try_recv().unwrap(), "immediate"); // Channel is now empty match rx.try_recv() { Err(TryRecvError::Empty) => println!("Nothing ready"), Err(TryRecvError::Disconnected) => println!("Closed"), Ok(v) => println!("Got: {}", v), } // Output: Nothing ready drop(tx); match rx.try_recv() { Err(TryRecvError::Disconnected) => println!("Closed and empty"), _ => {} } // Output: Closed and empty } ``` -------------------------------- ### flume::unbounded Source: https://context7.com/zesterer/flume/llms.txt Creates an unbounded channel with no maximum capacity. The `Sender::send` operation never blocks. Both sender and receiver endpoints can be cloned, enabling multiple producers and consumers. ```APIDOC ## flume::unbounded — Create an unbounded channel ### Description Creates a channel with no maximum capacity. `Sender::send` never blocks. Both endpoints implement `Clone`, allowing multiple producers and consumers. ### Usage Example ```rust use std::thread; fn main() { let (tx, rx) = flume::unbounded::(); // Clone sender for multiple producers let tx2 = tx.clone(); let producer1 = thread::spawn(move || { for i in 0..5 { tx.send(i).unwrap(); } }); let producer2 = thread::spawn(move || { for i in 5..10 { tx2.send(i).unwrap(); } }); producer1.join().unwrap(); producer2.join().unwrap(); // Collect all 10 messages let mut msgs: Vec = rx.try_iter().collect(); msgs.sort(); assert_eq!(msgs, (0..10).collect::>()); println!("Received: {:?}", msgs); // Output: Received: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] } ``` ``` -------------------------------- ### Sender::send_timeout / Sender::send_deadline Source: https://context7.com/zesterer/flume/llms.txt Sends a message with a maximum wait duration or an absolute deadline. Returns an error if the time expires before space is available in the channel. ```APIDOC ## Sender::send_timeout / Sender::send_deadline — Timed send Sends with a maximum wait duration or absolute deadline. Returns `Err(SendTimeoutError::Timeout(T))` if the time expires before space is available. ### Method `send_timeout(message: T, timeout: Duration)` or `send_deadline(message: T, deadline: Instant)` ### Parameters - `message` (T) - The message to send. - `timeout` (Duration) - The maximum duration to wait for space. - `deadline` (Instant) - The absolute time by which the message must be sent. ### Response - `Ok(())` - Message sent successfully. - `Err(SendTimeoutError::Timeout(T))` - The time expired before space was available. - `Err(SendTimeoutError::Disconnected(T))` - The receiver has been dropped. ### Request Example ```rust use flume::SendTimeoutError; use std::time::{Duration, Instant}; let (tx, _rx) = flume::bounded::<&str>(0); // Timeout variant match tx.send_timeout("hello", Duration::from_millis(50)) { Err(SendTimeoutError::Timeout(msg)) => println!("Timed out sending: {}", msg), Err(SendTimeoutError::Disconnected(msg)) => println!("Disconnected: {}", msg), Ok(()) => println!("Sent"), } // Deadline variant let deadline = Instant::now() + Duration::from_millis(50); match tx.send_deadline("world", deadline) { Err(SendTimeoutError::Timeout(msg)) => println!("Deadline passed: {}", msg), _ => {} } ``` ``` -------------------------------- ### Receiver::iter / Receiver::into_iter Source: https://context7.com/zesterer/flume/llms.txt Provides a blocking iterator that yields messages until all senders are dropped. `iter()` borrows the receiver, while `into_iter()` consumes it. ```APIDOC ## Receiver::iter / Receiver::into_iter — Blocking iterator Returns a blocking iterator that yields messages until all senders are dropped. `iter()` borrows the receiver; `into_iter()` consumes it. ### Method `iter()` or `into_iter()` ### Description This method allows for iterating over messages received from the channel in a blocking manner. The iteration stops automatically when the channel is closed (i.e., all senders have been dropped). ### Request Example ```rust use std::thread; let (tx, rx) = flume::unbounded(); thread::spawn(move || { for word in &["foo", "bar", "baz"] { tx.send(*word).unwrap(); } // tx dropped – iterator will end }); // Blocking iteration – stops when channel is closed let collected: Vec<&str> = rx.iter().collect(); assert_eq!(collected, vec!["foo", "bar", "baz"]); println!("Collected: {:?}", collected); ``` ``` -------------------------------- ### Blocking Iterator Receive Source: https://context7.com/zesterer/flume/llms.txt Use `Receiver::iter` or `Receiver::into_iter` to create a blocking iterator that yields messages until all senders are dropped. `iter()` borrows the receiver; `into_iter()` consumes it. ```rust use std::thread; fn main() { let (tx, rx) = flume::unbounded(); thread::spawn(move || { for word in &["foo", "bar", "baz"] { tx.send(*word).unwrap(); } // tx dropped – iterator will end }); // Blocking iteration – stops when channel is closed let collected: Vec<&str> = rx.iter().collect(); assert_eq!(collected, vec!["foo", "bar", "baz"]); println!("Collected: {:?}", collected); // Output: Collected: ["foo", "bar", "baz"] } ``` -------------------------------- ### Sender::same_channel / Receiver::same_channel — Identity check Source: https://context7.com/zesterer/flume/llms.txt Returns `true` if two senders (or two receivers) share the same underlying channel. ```rust fn main() { let (tx1, rx1) = flume::unbounded::(); let tx1b = tx1.clone(); let (tx2, _rx2) = flume::unbounded::(); assert!(tx1.same_channel(&tx1b)); assert!(!tx1.same_channel(&tx2)); assert!(rx1.same_channel(&rx1.clone())); println!("same_channel checks passed"); } ``` -------------------------------- ### Sender::try_send Source: https://context7.com/zesterer/flume/llms.txt Attempts to send a value without blocking. If the channel is at capacity, it returns `Err(TrySendError::Full(T))`. If all receivers are gone, it returns `Err(TrySendError::Disconnected(T))`. ```APIDOC ## Sender::try_send — Non-blocking send ### Description Attempts to send without blocking. Returns `Err(TrySendError::Full(T))` if the channel is at capacity, or `Err(TrySendError::Disconnected(T))` if all receivers are gone. ### Usage Example ```rust use flume::TrySendError; fn main() { let (tx, rx) = flume::bounded::(2); assert!(tx.try_send(1).is_ok()); assert!(tx.try_send(2).is_ok()); match tx.try_send(3) { Err(TrySendError::Full(val)) => println!("Channel full, could not send {}", val), Err(TrySendError::Disconnected(val)) => println!("No receivers, dropped {}", val), Ok(()) } // Output: Channel full, could not send 3 drop(rx); // drop all receivers match tx.try_send(4) { Err(TrySendError::Disconnected(val)) => println!("Disconnected, dropped {}", val), _ => {} } // Output: Disconnected, dropped 4 } ``` ``` -------------------------------- ### Sender::send Source: https://context7.com/zesterer/flume/llms.txt Performs a blocking send operation. This method will block on bounded channels if they are full, waiting for space to become available. It returns an error only if all receivers have been dropped. ```APIDOC ## Sender::send — Blocking send ### Description Sends a value, blocking on bounded full channels until space is available. Returns `Err(SendError)` only when all receivers have been dropped. ### Usage Example ```rust use std::thread; fn main() { let (tx, rx) = flume::bounded(1); let t = thread::spawn(move || { // Blocks here until the receiver reads the first message tx.send("msg1").unwrap(); tx.send("msg2").unwrap(); println!("All messages sent"); }); thread::sleep(std::time::Duration::from_millis(5)); assert_eq!(rx.recv().unwrap(), "msg1"); assert_eq!(rx.recv().unwrap(), "msg2"); t.join().unwrap(); } ``` ``` -------------------------------- ### Receiver::try_recv Source: https://context7.com/zesterer/flume/llms.txt Attempts to receive a message without blocking. Returns an error if no message is ready or if the channel is closed and empty. ```APIDOC ## Receiver::try_recv — Non-blocking receive Attempts to receive without blocking. Returns `Err(TryRecvError::Empty)` if no message is ready, or `Err(TryRecvError::Disconnected)` if closed and empty. ### Method `try_recv()` ### Response - `Ok(T)` - A message received from the channel. - `Err(TryRecvError::Empty)` - No message is currently available. - `Err(TryRecvError::Disconnected)` - The channel is closed and empty. ### Request Example ```rust use flume::TryRecvError; let (tx, rx) = flume::unbounded(); tx.send("immediate").unwrap(); // Message is available assert_eq!(rx.try_recv().unwrap(), "immediate"); // Channel is now empty match rx.try_recv() { Err(TryRecvError::Empty) => println!("Nothing ready"), Err(TryRecvError::Disconnected) => println!("Closed"), Ok(v) => println!("Got: {}", v), } drop(tx); match rx.try_recv() { Err(TryRecvError::Disconnected) => println!("Closed and empty"), _ => {} } ``` ``` -------------------------------- ### Blocking Receive Source: https://context7.com/zesterer/flume/llms.txt Use `Receiver::recv` to block until a message is available or all senders are dropped. Returns `Err(RecvError::Disconnected)` when the channel is closed and empty. ```rust use std::thread; fn main() { let (tx, rx) = flume::unbounded(); thread::spawn(move || { tx.send(42u32).unwrap(); tx.send(100u32).unwrap(); // tx dropped here, closing the channel }); loop { match rx.recv() { Ok(val) => println!("Got: {}", val), Err(flume::RecvError::Disconnected) => { println!("Channel closed"); break; } } } // Output: // Got: 42 // Got: 100 // Channel closed } ``` -------------------------------- ### Receiver::recv_timeout / Receiver::recv_deadline Source: https://context7.com/zesterer/flume/llms.txt Waits up to a duration or until an absolute deadline for a message. Returns an error if the time expires before a message is available. ```APIDOC ## Receiver::recv_timeout / Receiver::recv_deadline — Timed receive Waits up to a duration or until an absolute deadline for a message. Returns `Err(RecvTimeoutError::Timeout)` on expiry. ### Method `recv_timeout(timeout: Duration)` or `recv_deadline(deadline: Instant)` ### Parameters - `timeout` (Duration) - The maximum duration to wait for a message. - `deadline` (Instant) - The absolute time by which to receive the message. ### Response - `Ok(T)` - A message received from the channel. - `Err(RecvTimeoutError::Timeout)` - The time expired before a message was available. - `Err(RecvTimeoutError::Disconnected)` - The channel is closed and empty. ### Request Example ```rust use flume::RecvTimeoutError; use std::time::{Duration, Instant}; let (_tx, rx) = flume::unbounded::(); // Timeout variant – no sender ever sends match rx.recv_timeout(Duration::from_millis(50)) { Err(RecvTimeoutError::Timeout) => println!("Timed out waiting"), Err(RecvTimeoutError::Disconnected) => println!("Disconnected"), Ok(v) => println!("Got: {}", v), } // Deadline variant let (tx2, rx2) = flume::unbounded(); let deadline = Instant::now() + Duration::from_secs(1); std::thread::spawn(move || { std::thread::sleep(Duration::from_millis(10)); tx2.send("on time").unwrap(); }); match rx2.recv_deadline(deadline) { Ok(v) => println!("Got: {}", v), Err(RecvTimeoutError::Timeout) => println!("Too slow"), Err(RecvTimeoutError::Disconnected) => println!("Disconnected"), } ``` ``` -------------------------------- ### Sender::same_channel / Receiver::same_channel Source: https://context7.com/zesterer/flume/llms.txt Returns `true` if two senders (or two receivers) share the same underlying channel. ```APIDOC ## Sender::same_channel / Receiver::same_channel — Identity check ### Description Returns `true` if two senders (or two receivers) share the same underlying channel. ### Methods - `same_channel(&self, other: &Self) -> bool`: Checks if two senders or receivers refer to the same channel. ### Example ```rust let (tx1, rx1) = flume::unbounded::(); let tx1b = tx1.clone(); let (tx2, _rx2) = flume::unbounded::(); assert!(tx1.same_channel(&tx1b)); assert!(!tx1.same_channel(&tx2)); assert!(rx1.same_channel(&rx1.clone())); println!("same_channel checks passed"); ``` ``` -------------------------------- ### Receiver::drain Source: https://context7.com/zesterer/flume/llms.txt Takes a snapshot of all currently queued messages and returns a fixed-size iterator over them. This atomically removes all queued items in one lock acquisition and is not affected by concurrent senders after the call. ```APIDOC ## Receiver::drain — Snapshot drain ### Description Takes a snapshot of all currently queued messages and returns a fixed-size iterator over them. Unlike `try_iter`, this atomically removes all queued items in one lock acquisition and is not affected by concurrent senders after the call. ### Method `drain()` ### Example ```rust let (tx, rx) = flume::bounded(10); for i in 0..5 { tx.send(i).unwrap(); } let snapshot: Vec = rx.drain().collect(); println!("Drained: {:?}", snapshot); // [0, 1, 2, 3, 4] assert!(rx.is_empty()); ``` ``` -------------------------------- ### Receiver::drain — Snapshot drain Source: https://context7.com/zesterer/flume/llms.txt Takes a snapshot of all currently queued messages and returns a fixed-size iterator over them. Unlike `try_iter`, this atomically removes all queued items in one lock acquisition and is not affected by concurrent senders after the call. ```rust fn main() { let (tx, rx) = flume::bounded(10); for i in 0..5 { tx.send(i).unwrap(); } let snapshot: Vec = rx.drain().collect(); println!("Drained: {:?}", snapshot); // [0, 1, 2, 3, 4] assert!(rx.is_empty()); } ``` -------------------------------- ### Receiver::try_iter Source: https://context7.com/zesterer/flume/llms.txt Drains currently available messages from the receiver without blocking. It stops as soon as the queue is empty, even if senders are still alive. ```APIDOC ## Receiver::try_iter — Non-blocking iterator ### Description Drains currently available messages without blocking. Stops as soon as the queue is empty, even if senders are still alive. ### Method `try_iter()` ### Example ```rust let (tx, rx) = flume::unbounded(); tx.send(1).unwrap(); tx.send(2).unwrap(); tx.send(3).unwrap(); let available: Vec = rx.try_iter().collect(); println!("Available: {:?}", available); // Output: Available: [1, 2, 3] assert!(rx.is_empty()); ``` ``` -------------------------------- ### Receiver::recv Source: https://context7.com/zesterer/flume/llms.txt Blocks until a message is available or all senders have been dropped. Returns an error if the channel is closed and empty. ```APIDOC ## Receiver::recv — Blocking receive Blocks until a message is available or all senders have been dropped. Returns `Err(RecvError::Disconnected)` when the channel is closed and empty. ### Method `recv()` ### Response - `Ok(T)` - A message received from the channel. - `Err(RecvError::Disconnected)` - The channel is closed and empty. ### Request Example ```rust use std::thread; let (tx, rx) = flume::unbounded(); thread::spawn(move || { tx.send(42u32).unwrap(); tx.send(100u32).unwrap(); // tx dropped here, closing the channel }); loop { match rx.recv() { Ok(val) => println!("Got: {}", val), Err(flume::RecvError::Disconnected) => { println!("Channel closed"); break; } } } ``` ``` -------------------------------- ### Receiver::try_iter — Non-blocking iterator Source: https://context7.com/zesterer/flume/llms.txt Drains currently available messages without blocking. Stops as soon as the queue is empty, even if senders are still alive. ```rust fn main() { let (tx, rx) = flume::unbounded(); tx.send(1).unwrap(); tx.send(2).unwrap(); tx.send(3).unwrap(); // Only drains what is available right now let available: Vec = rx.try_iter().collect(); println!("Available: {:?}", available); // Output: Available: [1, 2, 3] assert!(rx.is_empty()); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.