### Tokio Integration: Producer and Consumer Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/async-ringbuf.md Shows how to integrate async-ringbuf with the Tokio runtime for concurrent producer and consumer tasks. This example demonstrates spawning tasks for pushing and popping items. ```rust use async_ringbuf::AsyncRb; use ringbuf::storage::Heap; use tokio::task; use std::sync::Arc; #[tokio::main] async fn main() { let rb = Arc::new(AsyncRb::>::new(16)); let prod_rb = rb.clone(); let cons_rb = rb.clone(); let producer = task::spawn(async move { for i in 0..10 { let msg = format!("Message {}", i); prod_rb.push(msg).await.ok(); } }); let consumer = task::spawn(async move { let mut count = 0; while let Some(_msg) = cons_rb.pop().await { count += 1; } count }); producer.await.unwrap(); let received = consumer.await.unwrap(); println!("Processed {} items", received); } ``` -------------------------------- ### Array Storage Usage Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/storage-backends.md Demonstrates creating and using a stack-allocated ring buffer with Array storage. This example shows basic push and pop operations. ```rust use ringbuf::{StaticRb, storage::Array}; use ringbuf::traits::*; const CAPACITY: usize = 8; // Create stack-allocated ring buffer let mut rb = StaticRb::::default(); let (mut prod, mut cons) = rb.split_ref(); prod.try_push(42).unwrap(); assert_eq!(cons.try_pop(), Some(42)); ``` -------------------------------- ### Simple Producer-Consumer Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/caching-wrapper.md Demonstrates a basic producer-consumer pattern using HeapRb with separate threads for producing and consuming items. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; use std::thread; fn example() { let rb = HeapRb::::new(64); let (mut prod, mut cons) = rb.split(); let producer = thread::spawn(move || { for i in 0..100 { prod.try_push(i).ok(); } }); let consumer = thread::spawn(move || { let mut sum = 0; while let Some(val) = cons.try_pop() { sum += val; } sum }); producer.join().unwrap(); let total = consumer.join().unwrap(); } ``` -------------------------------- ### Heap::new Constructor Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/storage-backends.md Creates a new Heap storage with a specified capacity. Panics if memory allocation fails. ```rust use ringbuf::storage::Heap; let storage = Heap::::new(16); // Allocates 64 bytes (16 * 4) on heap ``` -------------------------------- ### Create and Split HeapRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/types-and-traits.md Example of creating a new HeapRb and splitting it into producer and consumer. ```rust use ringbuf::HeapRb; let rb = HeapRb::::new(64); let (prod, cons) = rb.split(); ``` -------------------------------- ### Rust: Try Push Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/producer-trait.md Shows how to attempt inserting a single item into the ring buffer. Returns an error if the buffer is full. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(2); let (mut prod, _cons) = rb.split(); assert!(prod.try_push(1).is_ok()); assert!(prod.try_push(2).is_ok()); assert_eq!(prod.try_push(3), Err(3)); // Buffer is full ``` -------------------------------- ### Rust: Vacant Slices Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/producer-trait.md Illustrates how to get read-only access to the uninitialized memory slices in a ring buffer producer. Useful for checking available space. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let prod = rb.split_ref().0; let (left, right) = prod.vacant_slices(); println!("Vacant slots: {}", left.len() + right.len()); ``` -------------------------------- ### Create and Split StaticRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/types-and-traits.md Example of creating a new StaticRb and splitting it into producer and consumer using references. ```rust use ringbuf::StaticRb; let mut rb: StaticRb = Default::default(); let (prod, cons) = rb.split_ref(); ``` -------------------------------- ### Rust: Set Write Index Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/producer-trait.md Demonstrates how to directly set the write index of a producer. Use with caution, ensuring safety requirements are met. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let mut prod = rb.split_ref().0; unsafe { prod.set_write_index(2); } ``` -------------------------------- ### Heap::with_capacity Constructor Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/storage-backends.md Creates Heap storage with a specified capacity, returning a Result to handle potential allocation failures. ```rust use ringbuf::storage::Heap; match Heap::::with_capacity(16) { Ok(storage) => { /* use storage */ }, Err(_) => { /* handle allocation failure */ }, } ``` -------------------------------- ### Multiple Producers Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ringbuf-blocking.md Shows how to use multiple producer threads concurrently with a single blocking ring buffer. Each producer pushes a range of values. ```rust use ringbuf_blocking::BlockingRb; use std::thread; use std::sync::Arc; fn multi_producer() { let rb = Arc::new(BlockingRb::::new(64)); let mut handles = vec![]; for thread_id in 0..4 { let rb_clone = rb.clone(); handles.push(thread::spawn(move || { let (mut prod, _) = rb_clone.split(); for i in 0..10 { let val = thread_id * 100 + i; prod.push(val).ok(); } })); } for handle in handles { handle.join().unwrap(); } } ``` -------------------------------- ### Simple Async Ring Buffer Example Source: https://github.com/agerasev/ringbuf/blob/master/async/README.md Demonstrates the basic usage of AsyncHeapRb for asynchronous producer-consumer communication. It shows how to split the buffer, push items from a producer, and pop them from a consumer concurrently. ```rust use async_ringbuf::{traits::*, AsyncHeapRb}; use futures::{executor::block_on, join}; let rb = AsyncHeapRb::::new(10); let (prod, cons) = rb.split(); const N_ITERS: i32 = 100; join!( async move { let mut prod = prod; for i in 0..N_ITERS { prod.push(i).await.unwrap(); } }, async move { let mut cons = cons; for i in 0..N_ITERS { assert_eq!(cons.pop().await, Some(i)); } assert_eq!(cons.pop().await, None); }, ); ``` -------------------------------- ### Standard Producer-Consumer Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ringbuf-blocking.md Illustrates a typical multi-threaded producer-consumer pattern using a blocking ring buffer. The producer pushes integers, and the consumer pops them until the producer finishes. ```rust use ringbuf_blocking::BlockingRb; use std::thread; fn producer_consumer() { let rb = BlockingRb::::new(64); let (mut prod, mut cons) = rb.split(); let producer = thread::spawn(move || { for i in 0..100 { match prod.push(i) { Ok(()) => println!("Pushed {}", i), Err(e) => println!("Push failed: {:?}", e), } } }); let consumer = thread::spawn(move || { let mut count = 0; while let Ok(item) = cons.pop() { count += 1; println!("Consumed {}", item); } count }); producer.join().unwrap(); let total = consumer.join().unwrap(); println!("Total consumed: {}", total); } ``` -------------------------------- ### Rust: Advance Write Index Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/producer-trait.md Shows how to safely increment the write index after manually writing items. Ensure the first `count` items in the vacant area are initialized. ```rust use ringbuf::{HeapRb, traits::*}; use std::mem::MaybeUninit; let rb = HeapRb::::new(4); let mut prod = rb.split_ref().0; let (left, _right) = prod.vacant_slices_mut(); if !left.is_empty() { unsafe { left[0].write(42); prod.advance_write_index(1); } } ``` -------------------------------- ### Simple FIFO Pattern Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/INDEX.md Demonstrates the basic setup for a ring buffer using a heap-allocated ring buffer and splitting it into producer and consumer ends for simple FIFO operations. ```rust let rb = HeapRb::::new(capacity); let (mut prod, mut cons) = rb.split(); // Use prod and cons ``` -------------------------------- ### Get Ring Buffer Capacity Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/observer-trait.md Demonstrates how to retrieve the total capacity of the ring buffer. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(16); assert_eq!(rb.capacity().get(), 16); ``` -------------------------------- ### Multi-threaded Producer-Consumer with HeapRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/shared-and-local-rb.md Example of a multi-threaded producer-consumer pattern using HeapRb (which uses SharedRb internally). Spawns threads for producing and consuming data. ```rust use ringbuf::HeapRb; use std::thread; fn concurrent_processing() { let rb = HeapRb::::new(1024); let (mut prod, mut cons) = rb.split(); thread::spawn(move || { for i in 0..1000 { prod.try_push(i).ok(); } }); thread::spawn(move || { let mut total = 0u64; while let Some(val) = cons.try_pop() { total += val as u64; } println!("Sum: {}", total); }); } // Uses SharedRb for thread-safe access ``` -------------------------------- ### Check Ringbuf Boundaries Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/quick-start.md Safely handle full and empty conditions of the ring buffer. This example demonstrates pushing elements until the buffer is full and then popping them until it is empty, checking the boundary states. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; fn main() { let rb = HeapRb::::new(2); let (mut prod, mut cons) = rb.split(); // Push until full while prod.vacant_len() > 0 { prod.try_push(42).ok(); } println!("Buffer is full: {}", prod.is_full()); // Pop until empty while !cons.is_empty() { cons.try_pop().ok(); } println!("Buffer is empty: {}", cons.is_empty()); } ``` -------------------------------- ### Get Slices of Initialized Items Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/direct-wrapper.md Demonstrates how to obtain safe slices of initialized items from a consumer using `as_slices`. This is useful for inspecting the current state of the buffer. ```rust use ringbuf::{HeapRb, wrap::Cons, traits::*}; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(1).ok(); prod.try_push(2).ok(); let (left, right) = cons.as_slices(); assert_eq!(left, &[1, 2]); ``` -------------------------------- ### Multi-Threaded Ring Buffer with Thread Spawning Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/quick-start.md Shows how to share a heap-allocated ring buffer between multiple threads using `std::thread`. This example demonstrates a producer-consumer pattern across threads. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; use std::thread; fn main() { let rb = HeapRb::::new(64); let (mut prod, mut cons) = rb.split(); thread::spawn(move || { for i in 0..100 { prod.try_push(i).ok(); } }); thread::spawn(move || { let mut sum = 0; while let Some(val) = cons.try_pop() { sum += val; } println!("Sum: {}", sum); }); } ``` -------------------------------- ### Holding Read End Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ring-buffer-trait.md Demonstrates how to use `hold_read` to manage the read end's ownership status. This is typically used internally by wrapper types. ```rust use ringbuf::{HeapRb, traits::*}; let mut rb = HeapRb::::new(4); unsafe { let old = rb.hold_read(true); assert_eq!(old, false); assert!(rb.read_is_held()); } ``` -------------------------------- ### Rust: Vacant Slices Mut Example Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/producer-trait.md Demonstrates mutable access to uninitialized memory slices, followed by advancing the write index. Critical: no other mutating calls should occur between these operations. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let mut prod = rb.split_ref().0; let (left, _right) = prod.vacant_slices_mut(); if !left.is_empty() { unsafe { left[0].write(42); left[1].write(43); } unsafe { prod.advance_write_index(2); } } ``` -------------------------------- ### Copy Data Through Ringbuffer with I/O Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/advanced-usage.md This snippet shows how to use a ringbuf to facilitate copying data from a reader to a writer. It's a simplified example that would typically involve separate threads for reading and writing. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; use std::io::{Read, Write}; fn copy_through_ringbuffer( mut reader: R, mut writer: W, capacity: usize, ) -> std::io::Result { let rb = HeapRb::::new(capacity); let (mut prod, mut cons) = rb.split(); // Would typically be in different threads // but simplified for demonstration let mut total = 0; let mut buf = [0u8; 1024]; loop { match reader.read(&mut buf) { Ok(0) => break, // EOF Ok(n) => { prod.push_slice(&buf[..n]); total += n; } Err(e) => return Err(e), } // Write from consumer while cons.occupied_len() > 0 { let (left, right) = cons.as_slices(); if !left.is_empty() { writer.write_all(left)?; cons.skip(left.len()); } else if !right.is_empty() { writer.write_all(right)?; cons.skip(right.len()); } } } Ok(total) } ``` -------------------------------- ### Handle Ringbuf Errors Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/quick-start.md Implement robust error handling patterns for push and pop operations on the ring buffer. This example shows how to use `match` to handle potential errors like a full buffer during push or an empty buffer during pop. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; fn main() { let rb = HeapRb::::new(4); let (mut prod, mut cons) = rb.split(); // Handling push failure let msg = String::from("Hello"); match prod.try_push(msg) { Ok(()) => println!("Message sent"), Err(msg) => println!("Buffer full: {}", msg), } // Handling pop match cons.try_pop() { Some(item) => println!("Got: {}", item), None => println!("Nothing available"), } // Check before blocking operation if cons.is_empty() { println!("Buffer empty, producer might not be ready"); } } ``` -------------------------------- ### Construct, push, and pop from AsyncRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/async-ringbuf.md Shows how to create an AsyncRb, push an item, and then asynchronously pop it. Use this pattern to demonstrate basic producer-consumer interaction with an async ring buffer. ```rust use async_ringbuf::AsyncRb; use ringbuf::storage::Heap; #[tokio::main] async fn main() { let rb = AsyncRb::>::new(4); let (mut prod, mut cons) = rb.split(); prod.push(42).await.ok(); if let Some(val) = cons.pop().await { println!("Received: {}", val); } } ``` -------------------------------- ### Get Ring Buffer Read Index Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/observer-trait.md Shows how to get the current read index, indicating the oldest item. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(42).unwrap(); assert_eq!(cons.read_index(), 0); ``` -------------------------------- ### Get Ring Buffer Write Index Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/observer-trait.md Illustrates retrieving the current write index, pointing to the next available slot. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, _cons) = rb.split(); prod.try_push(42).unwrap(); assert_eq!(prod.write_index(), 1); ``` -------------------------------- ### Initialize StaticRb for Embedded Systems Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/storage-backends.md Shows how to initialize a StaticRb for use in embedded systems or scenarios requiring stack-allocated, fixed-size buffers without dynamic allocation. ```rust use ringbuf::StaticRb; use ringbuf::traits::*; // Stack-allocated, no dynamic allocation let mut rb: StaticRb = Default::default(); let (mut prod, mut cons) = rb.split_ref(); // Produce data prod.push_slice(&[1, 2, 3, 4]); // Consume data let mut buf = [0u8; 4]; cons.pop_slice(&mut buf); ``` -------------------------------- ### Get Occupied Length Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/observer-trait.md Returns the approximate number of items currently in the ring buffer. Note that this value can be stale in concurrent scenarios. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, mut cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); assert_eq!(cons.occupied_len(), 2); cons.try_pop(); assert_eq!(cons.occupied_len(), 1); ``` -------------------------------- ### unsafe_slices Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/observer-trait.md Provides low-level access to internal buffer slices. Returns two slices that together represent the buffer between indices `start` and `end`. ```APIDOC ## unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit], &[MaybeUninit]) ### Description Provides low-level access to internal buffer slices. Returns two slices that together represent the buffer between indices `start` and `end`. ### Method `unsafe_slices` ### Parameters #### Path Parameters - `start` (usize) - Required - The starting index of the slice. - `end` (usize) - Required - The ending index of the slice. ### Returns - `(&[MaybeUninit], &[MaybeUninit])`: Tuple of two slices; the second may be empty if the range doesn't wrap around the buffer end. ### Safety Requirements - The returned slice must not overlap with any other mutable slice existing at the same time. - Non-`Sync` items must not be accessed from multiple threads concurrently. ### Example ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, _cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); let (left, right) = unsafe { prod.unsafe_slices(0, 2) }; assert_eq!(left.len(), 2); assert_eq!(right.len(), 0); ``` ``` -------------------------------- ### Remove and Get Oldest Item Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Removes and returns the oldest item from the ring buffer following FIFO order. Returns None if the buffer is empty. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(2); let (mut prod, mut cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); assert_eq!(cons.try_pop(), Some(1)); assert_eq!(cons.try_pop(), Some(2)); assert_eq!(cons.try_pop(), None); ``` -------------------------------- ### Construct and push to AsyncRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/async-ringbuf.md Demonstrates the creation of an AsyncRb and pushing a single element. Use when you need to asynchronously add an item to a ring buffer. ```rust use async_ringbuf::AsyncRb; use ringbuf::storage::Heap; #[tokio::main] async fn main() { let rb = AsyncRb::>::new(4); let (mut prod, _) = rb.split(); prod.push(42).await.ok(); } ``` -------------------------------- ### Get First Element Mutable Reference Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Returns a mutable reference to the oldest item in the ring buffer. Useful for modifying the first element in place. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, mut cons) = rb.split(); prod.try_push(42).unwrap(); if let Some(first) = cons.first_mut() { *first = 100; } assert_eq!(cons.first(), Some(&100)); ``` -------------------------------- ### Get Vacant Length of Ring Buffer Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/observer-trait.md Returns the approximate number of free slots. Note that in concurrent scenarios, the actual count may differ. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, _cons) = rb.split(); prod.try_push(1).unwrap(); assert_eq!(prod.vacant_len(), 3); ``` -------------------------------- ### Constructor Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/direct-wrapper.md Creates a new direct wrapper for a given ring buffer reference. Panics if a conflicting wrapper already exists. ```APIDOC ## `fn new(rb: R) -> Self` ### Description Creates a new direct wrapper. ### Parameters #### Path Parameters - `rb` (R) - Required - Reference to the underlying ring buffer ### Panic Panics if a conflicting wrapper already exists. ### Return Value New direct wrapper. ### Example ```rust use ringbuf::{HeapRb, wrap::Prod}; use std::sync::Arc; let rb = Arc::new(HeapRb::::new(16)); let prod = Prod::new(rb.clone()); ``` ``` -------------------------------- ### Get Vacant Memory Slices Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/direct-wrapper.md Retrieves read-only slices representing the uninitialized memory available for writing. This is useful for inspecting available space before writing. ```rust use ringbuf::{HeapRb, wrap::Prod, traits::*}; let rb = HeapRb::::new(4); let prod = Prod::new(rb); let (left, right) = prod.vacant_slices(); println!("Vacant: {} + {}", left.len(), right.len()); ``` -------------------------------- ### Constructing a Blocking Ring Buffer Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ringbuf-blocking.md Demonstrates how to create a new BlockingRb with a specified capacity and then split it into producer and consumer halves. ```rust use ringbuf_blocking::BlockingRb; let rb = BlockingRb::::new(64); let (prod, cons) = rb.split(); ``` -------------------------------- ### Initialize LocalRb with Borrowed Pre-Allocated Buffer Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/storage-backends.md Demonstrates initializing a LocalRb by borrowing a pre-allocated buffer using the Ref storage. This is suitable for using memory from external sources like C libraries or static allocations. ```rust use ringbuf::{LocalRb, storage::Ref, traits::*}; use std::mem::MaybeUninit; // Existing buffer (e.g., from C library or static allocation) let mut buffer: [MaybeUninit; 64] = [MaybeUninit::uninit(); 64]; let storage = Ref::from(&mut buffer[..]); let mut rb = unsafe { LocalRb::from_raw_parts(storage, 0, 0) }; let (mut prod, mut cons) = rb.split_ref(); prod.try_push(123).unwrap(); ``` -------------------------------- ### Manual Synchronization with Frozen State Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/direct-wrapper.md Illustrates the manual synchronization pattern using `Prod::freeze` and `commit`. This allows for batching writes and controlling when changes become visible. ```rust use ringbuf::{HeapRb, wrap::Prod, traits::*}; let rb = HeapRb::::new(4); let prod = Prod::new(rb); // Freeze the state for manual control let mut frozen = prod.freeze(); // Write multiple items for i in 0..4 { frozen.try_push(i).ok(); } // Manually commit changes frozen.commit(); ``` -------------------------------- ### Get First Element Reference Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Returns an immutable reference to the oldest item in the ring buffer. Use when you need to inspect the first element without removing it. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); assert_eq!(cons.first(), Some(&1)); ``` -------------------------------- ### Basic Ring Buffer Usage with Ownership Transfer Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ring-buffer-trait.md Demonstrates basic ring buffer operations like pushing and popping while owning the buffer. It then shows how to split the buffer into producer and consumer for concurrent access. ```rust use ringbuf::{HeapRb, traits::*}; fn main() { let mut rb = HeapRb::::new(4); // Use while owning assert!(rb.try_push(42).is_ok()); assert_eq!(rb.try_pop(), Some(42)); // Split for concurrent use let (mut prod, mut cons) = rb.split(); prod.try_push(1).unwrap(); assert_eq!(cons.try_pop(), Some(1)); } ``` -------------------------------- ### Batch Insertion with CachingProd Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/caching-wrapper.md Shows how to perform batch insertions into a ring buffer using the `push_iter` method for efficiency. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; let rb = HeapRb::::new(256); let (mut prod, mut cons) = rb.split(); // Batch insert (single sync point) let items = vec![1, 2, 3, 4, 5]; let inserted = prod.push_iter(items.into_iter()); println!("Inserted: {}", inserted); ``` -------------------------------- ### Multi-Threaded Pattern Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/INDEX.md Illustrates how to set up a ring buffer for use across multiple threads by splitting it and sending the producer and consumer ends to different threads. ```rust let rb = HeapRb::::new(capacity); let (prod, cons) = rb.split(); // Send prod and cons to different threads ``` -------------------------------- ### Get Ring Buffer Elements as Slices Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Retrieves all items in the ring buffer as two slices in FIFO order. Useful for iterating over buffer contents without removal. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); let (left, right) = cons.as_slices(); assert_eq!(left, &[1, 2]); assert!(right.is_empty()); ``` -------------------------------- ### Create and Use HeapRb Ring Buffer Source: https://github.com/agerasev/ringbuf/blob/master/README.md Demonstrates creating a HeapRb, splitting it into producer and consumer, and performing push and pop operations. Use when dynamic memory allocation is acceptable. ```rust use ringbuf::{traits::*, HeapRb}; let rb = HeapRb::::new(2); let (mut prod, mut cons) = rb.split(); prod.try_push(0).unwrap(); prod.try_push(1).unwrap(); assert_eq!(prod.try_push(2), Err(2)); assert_eq!(cons.try_pop(), Some(0)); prod.try_push(2).unwrap(); assert_eq!(cons.try_pop(), Some(1)); assert_eq!(cons.try_pop(), Some(2)); assert_eq!(cons.try_pop(), None); ``` -------------------------------- ### Error Handling Pattern (Try Push) Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/INDEX.md Demonstrates how to handle potential errors when pushing an item using `try_push`, specifically when the buffer is full. ```rust match prod.try_push(item) { Ok(()) => { /* success */ }, Err(item) => { /* buffer full */ }, } ``` -------------------------------- ### Get Mutable Ring Buffer Slices Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Provides mutable access to all items in the ring buffer via two mutable slices. Allows in-place modification of buffer elements. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, mut cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); let (left, _right) = cons.as_mut_slices(); left[0] = 10; // Modify in place assert_eq!(cons.as_slices().0[0], 10); ``` -------------------------------- ### NUMA-Aware Producer-Consumer Threads Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/advanced-usage.md Demonstrates how to manage producer and consumer threads on different NUMA nodes for performance optimization on NUMA-aware systems. Requires external libraries for setting thread affinity. ```rust use ringbuf::HeapRb; use std::thread; fn numa_aware_producer_consumer() { let rb = HeapRb::::new(1024); let (mut prod, mut cons) = rb.split(); // Producer on specific NUMA node let producer = thread::spawn(move || { // Set thread affinity to NUMA node 0 (e.g., libnuma) for i in 0..1000 { prod.try_push(i).ok(); } }); // Consumer on different NUMA node let consumer = thread::spawn(move || { // Set thread affinity to NUMA node 1 let mut total = 0u64; while let Some(val) = cons.try_pop() { total += val; } total }); producer.join().unwrap(); let result = consumer.join().unwrap(); } ``` -------------------------------- ### Create and Use StaticRb Ring Buffer Source: https://github.com/agerasev/ringbuf/blob/master/README.md Shows how to create a StaticRb with a fixed size using default static memory. Suitable for embedded systems or when heap allocation is not desired. ```rust use ringbuf::{traits::*, StaticRb}; const RB_SIZE: usize = 1; let mut rb = StaticRb::::default(); let (mut prod, mut cons) = rb.split_ref(); assert_eq!(prod.try_push(123), Ok(())); assert_eq!(prod.try_push(321), Err(321)); assert_eq!(cons.try_pop(), Some(123)); assert_eq!(cons.try_pop(), None); ``` -------------------------------- ### Get Last Element Reference Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Returns an immutable reference to the most recently inserted item in the ring buffer. Note that in concurrent scenarios, this might not be the absolute latest if the producer is actively adding. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); assert_eq!(cons.last(), Some(&2)); ``` -------------------------------- ### Create Ref Storage and LocalRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/storage-backends.md Demonstrates creating a Ref storage from a mutable slice of MaybeUninit and initializing a LocalRb with it. This is useful for using existing memory buffers. ```rust use ringbuf::storage::Ref; use ringbuf::{LocalRb, traits::*}; use std::mem::MaybeUninit; let mut buffer: [MaybeUninit; 8] = [MaybeUninit::uninit(); 8]; let storage = Ref::from(&mut buffer[..]); let mut rb = LocalRb::>::from_raw_parts(storage, 0, 0); let (mut prod, mut cons) = rb.split_ref(); prod.try_push(42).unwrap(); ``` -------------------------------- ### Fallible Ring Buffer Initialization Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/advanced-usage.md Demonstrates how to handle potential allocation failures during ring buffer construction by providing a fallback to a smaller capacity. ```Rust use ringbuf::{HeapRb, storage::Heap}; fn create_with_fallback(capacity: usize) -> Result, Box> { // Try to allocate with requested capacity match Heap::::with_capacity(capacity) { Ok(storage) => { let rb = unsafe { HeapRb::from_raw_parts(storage, 0, 0) }; Ok(rb) } Err(_) => { // Fallback to smaller capacity let smaller = capacity / 2; let storage = Heap::with_capacity(smaller) .map_err(|_| "Failed to allocate even smaller buffer")?; let rb = unsafe { HeapRb::from_raw_parts(storage, 0, 0) }; Ok(rb) } } } ``` -------------------------------- ### Async Operations with AsyncRb and Tokio Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/quick-start.md Shows how to use `async_ringbuf::AsyncRb` with Tokio for asynchronous producer-consumer patterns. Operations `await` until completion, integrating with the Tokio runtime. ```rust use async_ringbuf::AsyncRb; use ringbuf::storage::Heap; use tokio::task; #[tokio::main] async fn main() { let rb = AsyncRb::>::new(16); let (mut prod, mut cons) = rb.split(); task::spawn(async move { for i in 0..10 { prod.push(i).await.ok(); } }); task::spawn(async move { while let Some(val) = cons.pop().await { println!("Got: {}", val); } }); } ``` -------------------------------- ### BlockingRb Construction Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ringbuf-blocking.md Demonstrates how to create a new BlockingRb instance and split it into producer and consumer halves. ```APIDOC ## BlockingRb - Thread-Blocking Ring Buffer **Module:** `ringbuf_blocking::rb::BlockingRb` `BlockingRb` wraps a `SharedRb` with condition variables for blocking on full/empty conditions. ### Type Parameters | Parameter | Constraint | Description | |-----------|-----------|-------------| | `S` | `Storage` | Backing storage (e.g., `Heap`) | ### Construction ```rust impl BlockingRb { pub fn new(capacity: usize) -> Self where S: Default; pub unsafe fn from_raw_parts( storage: S, read: usize, write: usize, ) -> Self; } ``` **Example:** ```rust use ringbuf_blocking::BlockingRb; let rb = BlockingRb::::new(64); let (prod, cons) = rb.split(); ``` ``` -------------------------------- ### Basic Single-Threaded Ring Buffer Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/quick-start.md Demonstrates the fundamental usage of a heap-allocated ring buffer for single-threaded applications. Shows how to create, push, and pop elements. ```rust use ringbuf::{HeapRb, traits::*}; fn main() { // Create a ring buffer with capacity of 4 let rb = HeapRb::::new(4); let (mut prod, mut cons) = rb.split(); // Push items prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); // Pop items assert_eq!(cons.try_pop(), Some(1)); assert_eq!(cons.try_pop(), Some(2)); assert_eq!(cons.try_pop(), None); // Empty } ``` -------------------------------- ### Get Occupied Slices (Read-Only) Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Provides read-only access to initialized memory slices within the ring buffer. Useful for inspecting items without removing them. The returned slices represent initialized items, with older elements at lower indices. ```Rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(1).unwrap(); prod.try_push(2).unwrap(); let (left, right) = cons.occupied_slices(); assert_eq!(left.len(), 2); ``` -------------------------------- ### Single-threaded Buffering with LocalRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/shared-and-local-rb.md Demonstrates single-threaded buffering using LocalRb with heap storage. Highlights faster performance due to no atomic overhead. ```rust use ringbuf::{LocalRb, storage::Heap}; fn single_thread_buffer() { let mut rb = LocalRb::>::new(256); // Faster for single-threaded: no atomic overhead { let (mut prod, mut cons) = rb.split_ref(); for i in 0..100 { prod.try_push(i).ok(); } while let Some(val) = cons.try_pop() { println!("{}", val); } } } ``` -------------------------------- ### Get Occupied Slices (Mutable) Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/consumer-trait.md Provides mutable access to initialized memory slices. This allows moving or modifying items in place. Crucially, it must be followed by a call to `advance_read_index` to reflect the number of items removed. Items must be removed from the beginning of the slices. ```Rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(4); let (mut prod, mut cons) = rb.split(); prod.try_push(42).unwrap(); unsafe { let (left, _) = cons.occupied_slices_mut(); let _value = left[0].assume_init_read(); cons.advance_read_index(1); } ``` -------------------------------- ### Heap Storage for SharedRb Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/shared-and-local-rb.md Demonstrates creating a SharedRb with heap-allocated storage. Requires the 'alloc' feature. ```rust use ringbuf::{SharedRb, storage::Heap}; let rb = SharedRb::>::new(16); ``` -------------------------------- ### Batch Operations Usage Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/types-and-traits.md Demonstrates batch insert using push_iter and batch read using pop_slice for efficient data transfer. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(256); let (mut prod, mut cons) = rb.split(); // Batch insert let data = vec![1, 2, 3, 4, 5]; prod.push_iter(data.into_iter()); // Batch read let mut out = vec![0; 5]; cons.pop_slice(&mut out); ``` -------------------------------- ### Performance Comparison: Without Caching Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/caching-wrapper.md Demonstrates the performance cost of using a non-caching producer, where each push operation involves an atomic write. This results in 1000 atomic operations for 1000 pushes. ```rust for i in 0..1000 { prod.try_push(i)?; } ``` -------------------------------- ### Pushing an Item with BlockingProd Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/ringbuf-blocking.md Shows how to push an item into a BlockingProd. It handles successful pushes and potential errors like the consumer being dropped or the thread being interrupted. ```rust use ringbuf_blocking::BlockingRb; let rb = BlockingRb::::new(4); let (mut prod, _cons) = rb.split(); match prod.push(42) { Ok(()) => println!("Pushed"), Err(e) => println!("Error: {:?}", e), } ``` -------------------------------- ### Create a New CachingProd Instance Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/caching-wrapper.md Creates a new CachingProd wrapper from a ring buffer reference. Panics if a wrapper with matching rights already exists. ```rust use ringbuf::{HeapRb, wrap::CachingProd}; use std::sync::Arc; let rb = Arc::new(HeapRb::::new(16)); let prod = CachingProd::new(rb.clone()); ``` -------------------------------- ### try_push Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/producer-trait.md Attempts to insert a single item into the ring buffer. Returns Ok(()) on success or Err(elem) if the buffer is full. ```APIDOC ## fn try_push(&mut self, elem: Self::Item) -> Result<(), Self::Item> ### Description Attempts to insert a single item into the ring buffer. ### Parameters #### Path Parameters - **elem** (Self::Item) - Required - The item to insert. ### Return value - `Ok(())` if the item was successfully inserted - `Err(elem)` if the buffer is full; the item is returned unchanged ### Example ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(2); let (mut prod, _cons) = rb.split(); assert!(prod.try_push(1).is_ok()); assert!(prod.try_push(2).is_ok()); assert_eq!(prod.try_push(3), Err(3)); // Buffer is full ``` ``` -------------------------------- ### Simple Owned Split Usage Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/types-and-traits.md Demonstrates a common pattern of splitting an owned ring buffer and performing push/pop operations. ```rust use ringbuf::{HeapRb, traits::*}; let rb = HeapRb::::new(16); let (mut prod, mut cons) = rb.split(); prod.try_push(42).ok(); if let Some(val) = cons.try_pop() { println!("{}", val); } ``` -------------------------------- ### Create Direct Producer Wrapper Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/direct-wrapper.md Instantiates a direct producer wrapper for a ring buffer. This is useful for scenarios where manual synchronization control is needed. ```rust use ringbuf::{HeapRb, wrap::Prod}; use std::sync::Arc; let rb = Arc::new(HeapRb::::new(16)); let prod = Prod::new(rb.clone()); ``` -------------------------------- ### StaticRb Single-Threaded Push and Pop Slices Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/heap-and-static-rb.md Illustrates using StaticRb in a single-threaded context with `split_ref`. It demonstrates pushing a slice of data and then popping it into another slice. ```rust use ringbuf::StaticRb; fn single_threaded() { let mut rb: StaticRb = Default::default(); let (mut prod, mut cons) = rb.split_ref(); prod.push_slice(&[1, 2, 3, 4]); let mut buf = [0; 4]; cons.pop_slice(&mut buf); assert_eq!(buf, [1, 2, 3, 4]); } ``` -------------------------------- ### HeapRb Producer-Consumer Thread Spawning Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/heap-and-static-rb.md Demonstrates creating a HeapRb and splitting it for use in separate producer and consumer threads. The producer pushes messages, and the consumer counts received messages. ```rust use ringbuf::HeapRb; use std::thread; fn producer_consumer() { let rb = HeapRb::::new(10); let (mut prod, mut cons) = rb.split(); let producer = thread::spawn(move || { for i in 0..5 { let msg = format!("Message {}", i); prod.try_push(msg).ok(); } }); let consumer = thread::spawn(move || { let mut count = 0; while let Some(msg) = cons.try_pop() { count += 1; } count }); producer.join().unwrap(); let received = consumer.join().unwrap(); } ``` -------------------------------- ### Batch Operations Pattern Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/INDEX.md Shows how to efficiently push multiple items using `push_iter` and pop multiple items into a buffer using `pop_slice`, optimizing synchronization. ```rust prod.push_iter(items.into_iter()); cons.pop_slice(&mut buffer); ``` -------------------------------- ### Single Producer, Single Async Consumer Pattern Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/async-ringbuf.md Illustrates a common pattern using tokio tasks for a producer and a consumer interacting with an AsyncRb. Use this for concurrent producer-consumer scenarios. ```rust use async_ringbuf::AsyncRb; use ringbuf::storage::Heap; use tokio::task; #[tokio::main] async fn producer_consumer() { let rb = AsyncRb::>::new(64); let (mut prod, mut cons) = rb.split(); task::spawn(async move { for i in 0..100 { prod.push(i).await.ok(); } }); task::spawn(async move { while let Some(val) = cons.pop().await { println!("Got: {}", val); } }); } ``` -------------------------------- ### Implement Custom Storage for Ringbuf Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/advanced-usage.md Shows how to implement the `Storage` trait for custom backing data structures. Suitable for non-allocating buffers, specialized memory alignment, or embedded regions. ```Rust use ringbuf::storage::Storage; use std::mem::MaybeUninit; use std::ops::Range; struct CustomStorage { data: Vec>, } unsafe impl Storage for CustomStorage { type Item = T; fn len(&self) -> usize { self.data.len() } fn as_mut_ptr(&self) -> *mut MaybeUninit { self.data.as_ptr() as *mut _ } unsafe fn slice(&self, range: Range) -> &[MaybeUninit] { &self.data[range] } unsafe fn slice_mut(&self, range: Range) -> &mut [MaybeUninit] { &mut *(self.data.as_ptr() as *mut [MaybeUninit]) } } ``` -------------------------------- ### Batch Operations with Ring Buffer Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/quick-start.md Demonstrates efficient batch insertion and reading using `push_iter` and `pop_slice` methods. Useful for processing larger chunks of data at once. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; fn main() { let rb = HeapRb::::new(256); let (mut prod, mut cons) = rb.split(); // Batch insert let data = vec![1, 2, 3, 4, 5]; let inserted = prod.push_iter(data.into_iter()); println!("Inserted: {}", inserted); // Batch read let mut output = vec![0; 5]; let read = cons.pop_slice(&mut output); println!("Read: {}", read); println!("Data: {:?}", &output[..read]); } ``` -------------------------------- ### Peeking at Data Before Popping Source: https://github.com/agerasev/ringbuf/blob/master/_autodocs/caching-wrapper.md Illustrates how to inspect the next available item in the consumer without removing it using `try_peek`. ```rust use ringbuf::HeapRb; use ringbuf::traits::*; let rb = HeapRb::::new(4); let (mut prod, cons) = rb.split(); prod.try_push(42).unwrap(); // Peek without removing if let Some(value) = cons.try_peek() { println!("Next value: {}", value); } ```