From da5757a71b7dab140b30c1a7bb94d5d2394a0490 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio <jorge@japaric.io> Date: Tue, 31 Oct 2017 17:59:47 +0100 Subject: [PATCH] add examples and cfail tests --- src/lib.rs | 143 ++++++++++++++++++++++++++++++++++++++++ src/ring_buffer/spsc.rs | 13 ++++ 2 files changed, 156 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 4c4abf2..c6228e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,148 @@ //! `static` friendly data structures that don't require dynamic memory //! allocation +//! +//! # Examples +//! +//! ## `Vec` +//! +//! ``` +//! use heapless::Vec; +//! +//! let mut xs: Vec<u8, [u8; 4]> = Vec::new(); +//! +//! assert!(xs.push(0).is_ok()); +//! assert!(xs.push(1).is_ok()); +//! assert!(xs.push(2).is_ok()); +//! assert!(xs.push(3).is_ok()); +//! assert!(xs.push(4).is_err()); // full +//! +//! assert_eq!(xs.pop(), Some(3)); +//! ``` +//! +//! ## `RingBuffer` +//! +//! ``` +//! use heapless::RingBuffer; +//! +//! let mut rb: RingBuffer<u8, [u8; 4]> = RingBuffer::new(); +//! +//! assert!(rb.enqueue(0).is_ok()); +//! assert!(rb.enqueue(1).is_ok()); +//! assert!(rb.enqueue(2).is_ok()); +//! assert!(rb.enqueue(3).is_err()); // full +//! +//! assert_eq!(rb.dequeue(), Some(0)); +//! ``` +//! +//! ### Single producer single consumer mode +//! +//! For use in *single core* systems like microcontrollers +//! +//! ``` +//! use heapless::RingBuffer; +//! +//! static mut RB: RingBuffer<Event, [Event; 4]> = RingBuffer::new(); +//! +//! enum Event { A, B } +//! +//! fn main() { +//! // NOTE(unsafe) beware of aliasing the `consumer` end point +//! let mut consumer = unsafe { RB.split().1 }; +//! +//! loop { +//! // `dequeue` is a lockless operation +//! match consumer.dequeue() { +//! Some(Event::A) => { /* .. */ }, +//! Some(Event::B) => { /* .. */ }, +//! None => { /* sleep */}, +//! } +//! # break +//! } +//! } +//! +//! // this is a different execution context that can preempt `main` +//! fn interrupt_handler() { +//! // NOTE(unsafe) beware of aliasing the `producer` end point +//! let mut producer = unsafe { RB.split().0 }; +//! # let condition = true; +//! +//! // .. +//! +//! if condition { +//! producer.enqueue(Event::A).unwrap(); +//! } else { +//! producer.enqueue(Event::B).unwrap(); +//! } +//! +//! // .. +//! } +//! ``` +//! +//! # `Send`-ness +//! +//! Collections of `Send`-able things are `Send` +//! +//! ``` +//! use heapless::{RingBuffer, Vec}; +//! use heapless::ring_buffer::{Consumer, Producer}; +//! +//! struct IsSend; +//! +//! unsafe impl Send for IsSend {} +//! +//! fn is_send<T>() where T: Send {} +//! +//! is_send::<Consumer<IsSend, [IsSend; 4]>>(); +//! is_send::<Producer<IsSend, [IsSend; 4]>>(); +//! is_send::<RingBuffer<IsSend, [IsSend; 4]>>(); +//! is_send::<Vec<IsSend, [IsSend; 4]>>(); +//! ``` +//! +//! Collections of not `Send`-able things are *not* `Send` +//! +//! ``` compile_fail +//! use std::marker::PhantomData; +//! use heapless::ring_buffer::Consumer; +//! +//! type NotSend = PhantomData<*const ()>; +//! +//! fn is_send<T>() where T: Send {} +//! +//! is_send::<Consumer<NotSend, [NotSend; 4]>>(); +//! ``` +//! +//! ``` compile_fail +//! use std::marker::PhantomData; +//! use heapless::ring_buffer::Producer; +//! +//! type NotSend = PhantomData<*const ()>; +//! +//! fn is_send<T>() where T: Send {} +//! +//! is_send::<Producer<NotSend, [NotSend; 4]>>(); +//! ``` +//! +//! ``` compile_fail +//! use std::marker::PhantomData; +//! use heapless::RingBuffer; +//! +//! type NotSend = PhantomData<*const ()>; +//! +//! fn is_send<T>() where T: Send {} +//! +//! is_send::<RingBuffer<NotSend, [NotSend; 4]>>(); +//! ``` +//! +//! ``` compile_fail +//! use std::marker::PhantomData; +//! use heapless::Vec; +//! +//! type NotSend = PhantomData<*const ()>; +//! +//! fn is_send<T>() where T: Send {} +//! +//! is_send::<Vec<NotSend, [NotSend; 4]>>(); +//! ``` #![deny(missing_docs)] #![feature(const_fn)] diff --git a/src/ring_buffer/spsc.rs b/src/ring_buffer/spsc.rs index 1258cce..37c0671 100644 --- a/src/ring_buffer/spsc.rs +++ b/src/ring_buffer/spsc.rs @@ -56,6 +56,12 @@ where } } +unsafe impl<T, A> Send for Consumer<T, A> +where + A: Unsize<[T]>, + T: Send, +{ +} /// A ring buffer "producer"; it can enqueue items into the ring buffer // NOTE the producer semantically owns the `tail` pointer of the ring buffer @@ -94,6 +100,13 @@ where } } +unsafe impl<T, A> Send for Producer<T, A> +where + A: Unsize<[T]>, + T: Send, +{ +} + #[cfg(test)] mod tests { use RingBuffer; -- GitLab