Expand description

Double Mapped Circular Buffer

  • Thread-safe.
  • Supports multiple readers.
  • Generic over the item type.
  • Provides access to all items (not n-1).
  • Supports Linux, macOS, Windows, and Android.
  • Sync, async, and non-blocking implementations.
  • Generic variant that allows specifying custom Notifiers to ease integration.
  • Underlying data structure (i.e., DoubleMappedBuffer) is exported to allow custom implementations.

Quick Start

let mut w = sync::Circular::new::<u32>().unwrap();
let mut r = w.add_reader();

// delay producing by 1 sec
let now = std::time::Instant::now();
let delay = std::time::Duration::from_millis(1000);

// producer thread
std::thread::spawn(move || {
    std::thread::sleep(delay);
    let w_buff = w.slice();
    for v in w_buff.iter_mut() {
        *v = 23;
    }
    let l = w_buff.len();
    w.produce(l);
});

// blocks until data becomes available
let r_buff = r.slice().unwrap();
assert!(now.elapsed() > delay);
for v in r_buff {
    assert_eq!(*v, 23);
}
let l = r_buff.len();
r.consume(l);

Commonalities

There are some commonalities between the implementations:

  • The Circular struct is a factory to create the Writer.
  • If there are no Readers, the Writer will not block but continuously overwrite the buffer.
  • The Writer has an add_reader() method to add Readers.
  • When the Writer is dropped, the Reader can read the remaining items. Afterwards, the slice() will return None.

Details

This circular buffer implementation maps the underlying buffer twice, back-to-back into the virtual address space of the process. This arrangement allows the circular buffer to present the available data sequentially, (i.e., as a slice) without having to worry about wrapping.

On Unix-based systems, the mapping is setup with a temporary file. This file is created in the folder, determined through std::env::temp_dir, which considers environment variables. This can be used, if the standard paths are not present of not writable on the platform.

Features

The async, nonblocking, and sync feature flags, allow to disable the corresponding implementations. By default, all are enabled. In addition, the generic flag allows to disable the generic implementation, leaving only the DoubleMappedBuffer.

Modules

Async Circular Buffer that can await until buffer space becomes available.

Underlying data structure that maps a buffer twice into virtual memory.

Circular Buffer with generic Notifier to implement custom wait/block behavior.

Non-blocking Circular Buffer that can only check if data is available right now.

Blocking Circular Buffer that blocks until data becomes available.