Skip to content
Snippets Groups Projects
Commit e841c8a6 authored by Jorge Aparicio's avatar Jorge Aparicio
Browse files

update the documentation

parent 09682676
No related branches found
No related tags found
No related merge requests found
//! `static` friendly data structures that don't require dynamic memory
//! allocation
#![deny(missing_docs)]
#![feature(const_fn)]
#![feature(shared)]
#![feature(unsize)]
......@@ -14,8 +15,6 @@ pub use ring_buffer::RingBuffer;
pub mod ring_buffer;
mod vec;
/// Error
/// Error raised when the buffer is full
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Error {
Full,
}
pub struct BufferFullError;
//! Ring buffer
use core::marker::{PhantomData, Unsize};
use core::ptr;
use untagged_option::UntaggedOption;
use Error;
use BufferFullError;
pub use self::spsc::{Consumer, Producer};
mod spsc;
/// An statically allocated ring buffer backed by an array with type `A`
/// An statically allocated ring buffer backed by an array `A`
pub struct RingBuffer<T, A>
where
// FIXME(rust-lang/rust#44580) use "const generics" instead of `Unsize`
......@@ -38,11 +40,13 @@ where
}
}
/// Returns the maximum number of elements the ring buffer can hold
pub fn capacity(&self) -> usize {
let buffer: &[T] = unsafe { self.buffer.as_ref() };
buffer.len() - 1
}
/// Returns the item in the front of the queue, or `None` if the queue is empty
pub fn dequeue(&mut self) -> Option<T> {
let n = self.capacity() + 1;
let buffer: &[T] = unsafe { self.buffer.as_ref() };
......@@ -56,7 +60,10 @@ where
}
}
pub fn enqueue(&mut self, item: T) -> Result<(), Error> {
/// Adds an `item` to the end of the queue
///
/// Returns `BufferFullError` if the queue is full
pub fn enqueue(&mut self, item: T) -> Result<(), BufferFullError> {
let n = self.capacity() + 1;
let buffer: &mut [T] = unsafe { self.buffer.as_mut() };
......@@ -68,10 +75,11 @@ where
self.tail = next_tail;
Ok(())
} else {
Err(Error::Full)
Err(BufferFullError)
}
}
/// Returns the number of elements in the queue
pub fn len(&self) -> usize {
if self.head > self.tail {
self.head - self.tail
......@@ -89,7 +97,7 @@ where
}
}
/// Mutable version of `iter`
/// Returns an iterator that allows modifying each value.
pub fn iter_mut(&mut self) -> IterMut<T, A> {
let len = self.len();
IterMut {
......@@ -137,6 +145,7 @@ where
}
}
/// An iterator over a ring buffer items
pub struct Iter<'a, T, A>
where
A: Unsize<[T]> + 'a,
......@@ -147,6 +156,7 @@ where
len: usize,
}
/// A mutable iterator over a ring buffer items
pub struct IterMut<'a, T, A>
where
A: Unsize<[T]> + 'a,
......
use core::ptr::{self, Shared};
use core::marker::Unsize;
use Error;
use BufferFullError;
use ring_buffer::RingBuffer;
impl<T, A> RingBuffer<T, A>
......@@ -9,6 +9,9 @@ where
A: Unsize<[T]>,
{
/// Splits a statically allocated ring buffer into producer and consumer end points
///
/// *Warning* the current implementation only supports single core processors. It's also fine to
/// use both end points on the same core of a multi-core processor.
pub fn split(&'static mut self) -> (Producer<T, A>, Consumer<T, A>) {
(
Producer {
......@@ -35,13 +38,14 @@ impl<T, A> Consumer<T, A>
where
A: Unsize<[T]>,
{
/// Returns the item in the front of the queue, or `None` if the queue is empty
pub fn dequeue(&mut self) -> Option<T> {
let rb = unsafe { self.rb.as_mut() };
let n = rb.capacity() + 1;
let buffer: &[T] = unsafe { rb.buffer.as_ref() };
// NOTE(volatile) the value of `tail` can change at any time in the context of the consumer
// so we inform this to the compiler using a volatile load
// NOTE(volatile) the value of `tail` can change at any time in the execution context of the
// consumer so we inform this to the compiler using a volatile load
if rb.head != unsafe { ptr::read_volatile(&rb.tail) } {
let item = unsafe { ptr::read(buffer.as_ptr().offset(rb.head as isize)) };
rb.head = (rb.head + 1) % n;
......@@ -67,14 +71,17 @@ impl<T, A> Producer<T, A>
where
A: Unsize<[T]>,
{
pub fn enqueue(&mut self, item: T) -> Result<(), Error> {
/// Adds an `item` to the end of the queue
///
/// Returns `BufferFullError` if the queue is full
pub fn enqueue(&mut self, item: T) -> Result<(), BufferFullError> {
let rb = unsafe { self.rb.as_mut() };
let n = rb.capacity() + 1;
let buffer: &mut [T] = unsafe { rb.buffer.as_mut() };
let next_tail = (rb.tail + 1) % n;
// NOTE(volatile) the value of `head` can change at any time in the context of the producer
// so we inform this to the compiler using a volatile load
// NOTE(volatile) the value of `head` can change at any time in the execution context of the
// producer so we inform this to the compiler using a volatile load
if next_tail != unsafe { ptr::read_volatile(&rb.head) } {
// NOTE(ptr::write) the memory slot that we are about to write to is uninitialized. We
// use `ptr::write` to avoid running `T`'s destructor on the uninitialized memory
......@@ -82,7 +89,7 @@ where
rb.tail = next_tail;
Ok(())
} else {
Err(Error::Full)
Err(BufferFullError)
}
}
}
......
......@@ -3,9 +3,9 @@ use core::{ops, ptr, slice};
use untagged_option::UntaggedOption;
use Error;
use BufferFullError;
/// [`Vec`] backed by a fixed size array
/// A [`Vec`], *vector*, backed by a fixed size array
///
/// [`Vec`]: https://doc.rust-lang.org/std/vec/struct.Vec.html
pub struct Vec<T, A>
......@@ -22,6 +22,7 @@ impl<T, A> Vec<T, A>
where
A: Unsize<[T]>,
{
/// Constructs a new, empty `Vec<T>` backed by the array `A`
pub const fn new() -> Self {
Vec {
_marker: PhantomData,
......@@ -30,19 +31,13 @@ where
}
}
/// Returns the maximum number of elements the vector can hold
pub fn capacity(&self) -> usize {
let buffer: &[T] = unsafe { self.buffer.as_ref() };
buffer.len()
}
pub fn iter(&self) -> slice::Iter<T> {
(**self).iter()
}
pub fn iter_mut(&mut self) -> slice::IterMut<T> {
(**self).iter_mut()
}
/// Removes the last element from a vector and return it, or `None` if it's empty
pub fn pop(&mut self) -> Option<T> {
let buffer: &[T] = unsafe { self.buffer.as_ref() };
......@@ -55,7 +50,10 @@ where
}
}
pub fn push(&mut self, item: T) -> Result<(), Error> {
/// Appends an element to the back of the collection
///
/// Returns `BufferFullError` if the vector is full
pub fn push(&mut self, item: T) -> Result<(), BufferFullError> {
let capacity = self.capacity();
let buffer: &mut [T] = unsafe { self.buffer.as_mut() };
......@@ -66,7 +64,7 @@ where
self.len += 1;
Ok(())
} else {
Err(Error::Full)
Err(BufferFullError)
}
}
}
......@@ -152,7 +150,6 @@ mod tests {
static mut COUNT: i32 = 0;
{
let mut v: Vec<Droppable, [Droppable; 2]> = Vec::new();
v.push(Droppable::new()).unwrap();
......@@ -231,5 +228,4 @@ mod tests {
assert_eq!(v.pop(), None);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment