1# ringbuf 2 3[![Crates.io][crates_badge]][crates] 4[![Docs.rs][docs_badge]][docs] 5[![Github Actions][github_badge]][github] 6[![Appveyor][appveyor_badge]][appveyor] 7[![License][license_badge]][license] 8 9[crates_badge]: https://img.shields.io/crates/v/ringbuf.svg 10[docs_badge]: https://docs.rs/ringbuf/badge.svg 11[github_badge]: https://github.com/agerasev/ringbuf/actions/workflows/test.yml/badge.svg 12[appveyor_badge]: https://ci.appveyor.com/api/projects/status/github/agerasev/ringbuf?branch=master&svg=true 13[license_badge]: https://img.shields.io/crates/l/ringbuf.svg 14 15[crates]: https://crates.io/crates/ringbuf 16[docs]: https://docs.rs/ringbuf 17[github]: https://github.com/agerasev/ringbuf/actions/workflows/test.yml 18[appveyor]: https://ci.appveyor.com/project/agerasev/ringbuf 19[license]: #license 20 21Lock-free single-producer single-consumer (SPSC) FIFO ring buffer with direct access to inner data. 22 23# Overview 24 25`RingBuffer` is the initial structure representing ring buffer itself. 26Ring buffer can be splitted into pair of `Producer` and `Consumer`. 27 28`Producer` and `Consumer` are used to append/remove elements to/from the ring buffer accordingly. They can be safely transfered between threads. 29Operations with `Producer` and `Consumer` are lock-free - they're succeded or failed immediately without blocking or waiting. 30 31Elements can be effectively appended/removed one by one or many at once. 32Also data could be loaded/stored directly into/from [`Read`]/[`Write`] instances. 33And finally, there are `unsafe` methods allowing thread-safe direct access in place to the inner memory being appended/removed. 34 35[`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html 36[`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html 37 38When building with nightly toolchain it is possible to run benchmarks via `cargo bench --features benchmark`. 39 40Also the crate could be used with `no_std` (but `alloc` is still required). 41 42# Examples 43 44## Simple example 45 46```rust 47use ringbuf::RingBuffer; 48 49let rb = RingBuffer::<i32>::new(2); 50let (mut prod, mut cons) = rb.split(); 51 52prod.push(0).unwrap(); 53prod.push(1).unwrap(); 54assert_eq!(prod.push(2), Err(2)); 55 56assert_eq!(cons.pop().unwrap(), 0); 57 58prod.push(2).unwrap(); 59 60assert_eq!(cons.pop().unwrap(), 1); 61assert_eq!(cons.pop().unwrap(), 2); 62assert_eq!(cons.pop(), None); 63``` 64 65## Message transfer 66 67This is more complicated example of transfering text message between threads. 68 69```rust 70use std::io::Read; 71use std::thread; 72use std::time::Duration; 73 74use ringbuf::RingBuffer; 75 76let buf = RingBuffer::<u8>::new(10); 77let (mut prod, mut cons) = buf.split(); 78 79let smsg = "The quick brown fox jumps over the lazy dog"; 80 81let pjh = thread::spawn(move || { 82 println!("-> sending message: '{}'", smsg); 83 84 let zero = [0]; 85 let mut bytes = smsg.as_bytes().chain(&zero[..]); 86 loop { 87 if prod.is_full() { 88 println!("-> buffer is full, waiting"); 89 thread::sleep(Duration::from_millis(1)); 90 } else { 91 let n = prod.read_from(&mut bytes, None).unwrap(); 92 if n == 0 { 93 break; 94 } 95 println!("-> {} bytes sent", n); 96 } 97 } 98 99 println!("-> message sent"); 100}); 101 102let cjh = thread::spawn(move || { 103 println!("<- receiving message"); 104 105 let mut bytes = Vec::<u8>::new(); 106 loop { 107 if cons.is_empty() { 108 if bytes.ends_with(&[0]) { 109 break; 110 } else { 111 println!("<- buffer is empty, waiting"); 112 thread::sleep(Duration::from_millis(1)); 113 } 114 } else { 115 let n = cons.write_into(&mut bytes, None).unwrap(); 116 println!("<- {} bytes received", n); 117 } 118 } 119 120 assert_eq!(bytes.pop().unwrap(), 0); 121 let msg = String::from_utf8(bytes).unwrap(); 122 println!("<- message received: '{}'", msg); 123 124 msg 125}); 126 127pjh.join().unwrap(); 128let rmsg = cjh.join().unwrap(); 129 130assert_eq!(smsg, rmsg); 131``` 132 133## License 134 135Licensed under either of 136 137 * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 138 * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 139 140at your option. 141 142### Contribution 143 144Unless you explicitly state otherwise, any contribution intentionally submitted 145for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 146additional terms or conditions. 147