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