MCPcopy Index your code
hub / github.com/agerasev/ringbuf

github.com/agerasev/ringbuf @v0.4.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.4.0 ↗ · + Follow
449 symbols 1,286 edges 72 files 88 documented · 20%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

ringbuf

Crates.io Docs.rs Gitlab CI License

Lock-free SPSC FIFO ring buffer with direct access to inner data.

Features

  • Lock-free operations - they succeed or fail immediately without blocking or waiting.
  • Arbitrary item type (not only Copy).
  • Items can be inserted and removed one by one or many at once.
  • Thread-safe direct access to the internal ring buffer memory.
  • Read and Write implementation.
  • Overwriting insertion support.
  • Different types of buffers and underlying storages.
  • Can be used without std and even without alloc (using only statically-allocated memory).
  • Async and blocking versions (see this section).

Usage

At first you need to create the ring buffer itself. HeapRb is recommended but you may choose another one.

After the ring buffer is created it may be splitted into pair of Producer and Consumer. Producer is used to insert items to the ring buffer, consumer - to remove items from it.

Types

There are several types of ring buffers provided:

  • LocalRb. Only for single-threaded use.
  • SharedRb. Can be shared between threads. Its frequently used instances:
  • HeapRb. Contents are stored in dynamic memory. Recommended for use in most cases.
  • StaticRb. Contents can be stored in statically-allocated memory.

You may also provide your own generic parameters.

Performance

SharedRb needs to synchronize CPU cache between CPU cores. This synchronization has some overhead. To avoid multiple unnecessary synchronizations you may use methods that operate many items at once (push_slice/push_iter, pop_slice/pop_iter, etc.) or you can freeze producer or consumer and then synchronize threads manually (see items in frozen module).

For single-threaded usage LocalRb is recommended because it is slightly faster than SharedRb due to absence of CPU cache synchronization.

Examples

Simple

use ringbuf::{traits::*, HeapRb};

let rb = HeapRb::<i32>::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);

No heap

use ringbuf::{traits::*, StaticRb};

const RB_SIZE: usize = 1;
let mut rb = StaticRb::<i32, RB_SIZE>::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);

Overwrite

Ring buffer can be used in overwriting mode when insertion overwrites the latest element if the buffer is full.

use ringbuf::{traits::*, HeapRb};

let mut rb = HeapRb::<i32>::new(2);

assert_eq!(rb.push_overwrite(0), None);
assert_eq!(rb.push_overwrite(1), None);
assert_eq!(rb.push_overwrite(2), Some(0));

assert_eq!(rb.try_pop(), Some(1));
assert_eq!(rb.try_pop(), Some(2));
assert_eq!(rb.try_pop(), None);

Note that push_overwrite requires exclusive access to the ring buffer so to perform it concurrently you need to guard the ring buffer with mutex or some other lock.

Derived crates

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Extension points exported contracts — how you extend this code

Observer (Interface)
Ring buffer observer. Can observe ring buffer state but cannot safely access its data. [8 implementers]
src/traits/observer.rs
Wrap (Interface)
Ring buffer wrapper that contains reference to the ring buffer inside. [5 implementers]
src/wrap/traits.rs
Storage (Interface)
Abstract storage for the ring buffer. Storage items must be stored as a contiguous array. # Safety Must not alias wit [4 …
src/storage.rs
RbRef (Interface)
Abstract pointer to the owning ring buffer. # Safety Implementation must be fair (e.g. not replacing pointers between [3 …
src/rb/traits.rs
Instant (Interface)
Elapsed time counter. [1 implementers]
blocking/src/sync.rs
AsyncRbRef (Interface)
(no doc) [1 implementers]
async/src/rb.rs
Split (Interface)
Split the ring buffer onto producer and consumer. [8 implementers]
src/traits/split.rs
Semaphore (Interface)
Binary semaphore. [1 implementers]
blocking/src/sync.rs

Core symbols most depended-on inside this repo

len
called by 52
src/storage.rs
split_ref
called by 42
src/rb/local.rs
try_push
called by 38
src/traits/producer.rs
rb
called by 26
src/wrap/traits.rs
base
called by 23
async/src/wrap/mod.rs
push_slice
called by 23
src/traits/producer.rs
iter
called by 22
src/traits/consumer.rs
clone
called by 19
src/wrap/direct.rs

Shape

Method 292
Function 106
Class 30
Interface 20
Enum 1

Languages

Rust100%

Modules by API surface

src/traits/consumer.rs40 symbols
src/wrap/frozen.rs23 symbols
src/rb/local.rs21 symbols
src/wrap/direct.rs20 symbols
src/wrap/caching.rs19 symbols
src/rb/shared.rs19 symbols
blocking/src/rb.rs18 symbols
async/src/rb.rs18 symbols
src/traits/observer.rs17 symbols
src/traits/producer.rs16 symbols
blocking/src/sync.rs14 symbols
async/src/traits/producer.rs14 symbols

For agents

$ claude mcp add ringbuf \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact