1//! Lock-free SPSC FIFO ring buffer with direct access to inner data.
2//!
3//! # Features
4//!
5//! + Lock-free operations - they succeed or fail immediately without blocking or waiting.
6//! + Arbitrary item type (not only [`Copy`]).
7//! + Items can be inserted and removed one by one or many at once.
8//! + Thread-safe direct access to the internal ring buffer memory.
9//! + [`Read`](`std::io::Read`) and [`Write`](`std::io::Write`) implementation.
10//! + Can be used without `std` and even without `alloc` (using only statically-allocated memory).
11//! + [Experimental `async`/`.await` support](https://github.com/agerasev/async-ringbuf).
12//!
13//! # Usage
14//!
15//! At first you need to create the ring buffer itself. [`HeapRb`] is recommended but you may [choose another one](#types).
16//!
17//! After the ring buffer is created it may be splitted into pair of [`Producer`] and [`Consumer`].
18//! [`Producer`] is used to insert items to the ring buffer, [`Consumer`] - to remove items from it.
19//! For [`SharedRb`] and its derivatives they can be used in different threads.
20//!
21//! Also you can use the ring buffer without splitting at all via methods provided by [`Rb`] trait.
22//!
23//! # Types
24//!
25//! There are several types of ring buffers provided:
26//!
27//! + [`LocalRb`]. Only for single-threaded use.
28//! + [`SharedRb`]. Can be shared between threads. Its derivatives:
29//! + [`HeapRb`]. Contents are stored in dynamic memory. *Recommended for use in most cases.*
30//! + [`StaticRb`]. Contents can be stored in statically-allocated memory.
31//!
32//! # Performance
33//!
34//! [`SharedRb`] needs to synchronize CPU cache between CPU cores. This synchronization has some overhead.
35//! To avoid multiple unnecessary synchronizations you may use postponed mode of operation (see description for [`Producer#mode`] and [`Consumer#mode`])
36//! or methods that operate many items at once ([`Producer::push_slice`]/[`Producer::push_iter`], [`Consumer::pop_slice`], etc.).
37//!
38//! For single-threaded usage [`LocalRb`] is recommended because it is faster than [`SharedRb`] due to absence of CPU cache synchronization.
39//!
40//! ## Benchmarks
41//!
42//! You may see typical performance of different methods in benchmarks:
43//!
44//! ```bash
45//! cargo +nightly bench --features bench
46//! ```
47//!
48//! Nightly toolchain is required.
49//!
50//! # Examples
51//!
52#![cfg_attr(
53 feature = "alloc",
54 doc = r##"
55## Simple
56
57```rust
58use ringbuf::HeapRb;
59
60# fn main() {
61let rb = HeapRb::<i32>::new(2);
62let (mut prod, mut cons) = rb.split();
63
64prod.push(0).unwrap();
65prod.push(1).unwrap();
66assert_eq!(prod.push(2), Err(2));
67
68assert_eq!(cons.pop(), Some(0));
69
70prod.push(2).unwrap();
71
72assert_eq!(cons.pop(), Some(1));
73assert_eq!(cons.pop(), Some(2));
74assert_eq!(cons.pop(), None);
75# }
76```
77"##
78)]
79#![doc = r##"
80## No heap
81
82```rust
83use ringbuf::StaticRb;
84
85# fn main() {
86const RB_SIZE: usize = 1;
87let mut rb = StaticRb::<i32, RB_SIZE>::default();
88let (mut prod, mut cons) = rb.split_ref();
89
90assert_eq!(prod.push(123), Ok(()));
91assert_eq!(prod.push(321), Err(321));
92
93assert_eq!(cons.pop(), Some(123));
94assert_eq!(cons.pop(), None);
95# }
96```
97"##]
98#![cfg_attr(
99 feature = "std",
100 doc = r##"
101## Overwrite
102
103Ring buffer can be used in overwriting mode when insertion overwrites the latest element if the buffer is full.
104
105```rust
106use ringbuf::{HeapRb, Rb};
107
108# fn main() {
109let mut rb = HeapRb::<i32>::new(2);
110
111assert_eq!(rb.push_overwrite(0), None);
112assert_eq!(rb.push_overwrite(1), None);
113assert_eq!(rb.push_overwrite(2), Some(0));
114
115assert_eq!(rb.pop(), Some(1));
116assert_eq!(rb.pop(), Some(2));
117assert_eq!(rb.pop(), None);
118# }
119```
120
121Note that [`push_overwrite`](`Rb::push_overwrite`) requires exclusive access to the ring buffer
122so to perform it concurrently you need to guard the ring buffer with [`Mutex`](`std::sync::Mutex`) or some other lock.
123"##
124)]
125//! ## `async`/`.await`
126//!
127//! There is an experimental crate [`async-ringbuf`](https://github.com/agerasev/async-ringbuf)
128//! which is built on top of `ringbuf` and implements asynchronous ring buffer operations.
129//!
130#![no_std]
131#![cfg_attr(feature = "bench", feature(test))]
132
133#[cfg(feature = "alloc")]
134extern crate alloc;
135#[cfg(feature = "std")]
136extern crate std;
137
138mod alias;
139mod utils;
140
141/// [`Consumer`] and additional types.
142pub mod consumer;
143/// [`Producer`] and additional types.
144pub mod producer;
145/// Ring buffer traits and implementations.
146pub mod ring_buffer;
147mod transfer;
148
149#[cfg(feature = "alloc")]
150pub use alias::{HeapConsumer, HeapProducer, HeapRb};
151pub use alias::{StaticConsumer, StaticProducer, StaticRb};
152pub use consumer::Consumer;
153pub use producer::Producer;
154pub use ring_buffer::{LocalRb, Rb, SharedRb};
155pub use transfer::transfer;
156
157#[cfg(test)]
158mod tests;
159
160#[cfg(feature = "bench")]
161extern crate test;
162#[cfg(feature = "bench")]
163mod benchmarks;
164