scroll_ring/
lib.rs

1//! Structures for MPSC text streaming
2//!
3//! The goal of the data structure provided by this crate is to cater for the needs of stdout-style
4//! text streaming over a lossy network, which results in thee requirements:
5//!
6//! * store a byte data stream in a no-std/no-alloc buffer,
7//! * be multi-producer (so that threads or even signals/interrupts can write to it),
8//! * never block (calls may take O(n) time for the processed data, but even with much reading and
9//!   writing it mustn't take significantly longer -- ideally constant-time, but given atomics are
10//!   generally not constan-time, maybe "as fast as the atomics are"?),
11//! * not interleave contiguous writes,
12//! * not lose any writes (it's OK to admit overflows, but keep track of how many bytes overflew),
13//! * keep old data around for as long as possible until it is overwritten,
14//! * offer a reader a chance to get a reasonable chunk of data even when it's way too slow for the
15//!   current writes (think taking a snapshot of data scolling by), and
16//! * overflow as little as possible.
17//!
18//! Overflowing data may not even hit the buffer, for example when a slice larger than the buffer
19//! is written, or when (large amounts of) data is to be written while a read happens, or while a
20//! write from a slow process happens -- either way, the written bytes are counted, they're just
21//! not available for reading (just as they would have been if the reader were merely too slow).
22//!
23//! This is the minimal implementation that solely on "overflow as little as possible" to get a
24//! waaaay easier implementation. Better options are:
25//!
26//! * A perfect implementation would have atomics everywhere, and as long as there are no reads (or
27//!   no writes from threads with such low priority that higher priority writes wrap around before
28//!   the low priority write is done memcpy'ing), there would be no overflow. That'd be ideal, but
29//!   is really hard.
30//!
31//! * An intermediate implementation would allow parallel writes, but have a brief period of
32//!   locking the administrative part of the data structure when operations start and stop. (Thus,
33//!   overflows might happen merely because an interrupt triggers at an inopportune time).
34//!
35//!   Both these versions would probably need a bitfield of valid bytes (or a list of busy
36//!   writers), because due to variable thread priorities concurrent writes don't finish in the
37//!   opposite order of being started.
38//!
39//! * What is currently provided is about the dumbest possible version. For the whole duration of
40//!   reading or writing, the data structure stays locked, and any overflows are recorded into an
41//!   atomic field next to the locked structure.
42//!
43//!   The [ringbuf] data structures are used in single-threaded mode here; there is a
44//!   multi-threaded mode that could go some way implementing the others.
45#![no_std]
46
47mod minimal;
48mod util;
49
50pub use minimal::{Buffer, BufferUnavailable, ReadErr};