1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
//! # BBQueue //! //! BBQueue, short for "BipBuffer Queue", is a Single Producer Single Consumer, //! lockless, no_std, thread safe, queue, based on [BipBuffers]. For more info on //! the design of the lock-free algorithm used by bbqueue, see [this blog post]. //! //! For a 90 minute guided tour of BBQueue, you can also view this [guide on YouTube]. //! //! [guide on YouTube]: https://www.youtube.com/watch?v=ngTCf2cnGkY //! [BipBuffers]: https://www.codeproject.com/Articles/3479/%2FArticles%2F3479%2FThe-Bip-Buffer-The-Circular-Buffer-with-a-Twist //! [this blog post]: https://ferrous-systems.com/blog/lock-free-ring-buffer/ //! //! BBQueue is designed (primarily) to be a First-In, First-Out queue for use with DMA on embedded //! systems. //! //! While Circular/Ring Buffers allow you to send data between two threads (or from an interrupt to //! main code), you must push the data one piece at a time. With BBQueue, you instead are granted a //! block of contiguous memory, which can be filled (or emptied) by a DMA engine. //! //! ## Local usage //! //! ```rust, no_run //! # #[cfg(feature = "atomic")] //! # use bbqueue::atomic::{BBBuffer, consts::*}; //! # #[cfg(not(feature = "atomic"))] //! # use bbqueue::cm_mutex::{BBBuffer, consts::*}; //! # //! // Create a buffer with six elements //! let bb: BBBuffer<U6> = BBBuffer::new(); //! let (mut prod, mut cons) = bb.try_split().unwrap(); //! //! // Request space for one byte //! let mut wgr = prod.grant_exact(1).unwrap(); //! //! // Set the data //! wgr[0] = 123; //! //! assert_eq!(wgr.len(), 1); //! //! // Make the data ready for consuming //! wgr.commit(1); //! //! // Read all available bytes //! let rgr = cons.read().unwrap(); //! //! assert_eq!(rgr[0], 123); //! //! // Release the space for later writes //! rgr.release(1); //! ``` //! //! ## Static usage //! //! ```rust, no_run //! # #[cfg(feature = "atomic")] //! # use bbqueue::atomic::{BBBuffer, ConstBBBuffer, consts::*}; //! # #[cfg(not(feature = "atomic"))] //! # use bbqueue::cm_mutex::{BBBuffer, ConstBBBuffer, consts::*}; //! # //! // Create a buffer with six elements //! static BB: BBBuffer<U6> = BBBuffer( ConstBBBuffer::new() ); //! //! fn main() { //! // Split the bbqueue into producer and consumer halves. //! // These halves can be sent to different threads or to //! // an interrupt handler for thread safe SPSC usage //! let (mut prod, mut cons) = BB.try_split().unwrap(); //! //! // Request space for one byte //! let mut wgr = prod.grant_exact(1).unwrap(); //! //! // Set the data //! wgr[0] = 123; //! //! assert_eq!(wgr.len(), 1); //! //! // Make the data ready for consuming //! wgr.commit(1); //! //! // Read all available bytes //! let rgr = cons.read().unwrap(); //! //! assert_eq!(rgr[0], 123); //! //! // Release the space for later writes //! rgr.release(1); //! //! // The buffer cannot be split twice //! assert!(BB.try_split().is_err()); //! } //! ``` //! //! ## Features //! //! By default BBQueue uses atomic operations which are available on most platforms. However on some //! (mostly embedded) platforms atomic support is limited and with the default features you will get //! a compiler error about missing atomic methods. //! //! This crate contains special support for Cortex-M0(+) targets with the `thumbv6` feature. By //! enabling the feature, unsupported atomic operations will be replaced with critical sections //! implemented by disabling interrupts. The critical sections are very short, a few instructions at //! most, so they should make no difference to most applications. #![cfg_attr(not(feature = "std"), no_std)] #![deny(missing_docs)] #![deny(warnings)] mod bbbuffer; pub use bbbuffer::*; /// There are no longer separate `atomic` and `cm_mutex` modules. You can just use the types at the /// crate root. #[deprecated( note = "There are no longer separate 'atomic' and 'cm_mutex' modules. You can just use the types at the crate root." )] pub mod atomic { pub use crate::bbbuffer::*; } /// There are no longer separate `atomic` and `cm_mutex` modules. You can just use the types at the /// crate root. #[deprecated( note = "There are no longer separate 'atomic' and 'cm_mutex' modules. You can just use the types at the crate root." )] pub mod cm_mutex { pub use crate::bbbuffer::*; } pub mod framed; mod vusize; use core::result::Result as CoreResult; pub use generic_array::ArrayLength; /// Result type used by the `BBQueue` interfaces pub type Result<T> = CoreResult<T, Error>; /// Error type used by the `BBQueue` interfaces #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Error { /// The buffer does not contain sufficient size for the requested action InsufficientSize, /// Unable to produce another grant, a grant of this type is already in /// progress GrantInProgress, /// Unable to split the buffer, as it has already been split AlreadySplit, }