From 9d8210761c9d8df031cd2c4500d1a6ac250ca715 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio <jorge@japaric.io> Date: Wed, 22 Nov 2017 20:56:32 +0100 Subject: [PATCH] v0.2.0 --- CHANGELOG.md | 21 ++++++++++++++++++++- src/ring_buffer/mod.rs | 3 +-- src/ring_buffer/spsc.rs | 6 +++++- src/vec.rs | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63644e8..90c0530 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,27 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [v0.2.0] - 2017-11-22 + +### Added + +- A single producer single consumer mode to `RingBuffer`. + +- A `truncate` method to `Vec`. + +### Changed + +- [breaking-change] Both `Vec::new` and `RingBuffer::new` no longer require an initial value. The + signature of `new` is now `const fn() -> Self`. + +- [breaking-change] The error type of all operations that may fail has changed from `()` to + `BufferFullError`. + +- Both `RingBuffer` and `Vec` now support arrays of *any* size for their backup storage. + ## [v0.1.0] - 2017-04-27 - Initial release -[Unreleased]: https://github.com/japaric/heapless/compare/v0.1.0...HEAD +[Unreleased]: https://github.com/japaric/heapless/compare/v0.2.0...HEAD +[v0.2.0]: https://github.com/japaric/heapless/compare/v0.1.0...v0.2.0 diff --git a/src/ring_buffer/mod.rs b/src/ring_buffer/mod.rs index 0ae68a7..faa5f0b 100644 --- a/src/ring_buffer/mod.rs +++ b/src/ring_buffer/mod.rs @@ -6,9 +6,8 @@ use core::{intrinsics, ptr}; use untagged_option::UntaggedOption; -use BufferFullError; - pub use self::spsc::{Consumer, Producer}; +use BufferFullError; mod spsc; diff --git a/src/ring_buffer/spsc.rs b/src/ring_buffer/spsc.rs index 4260bae..955d774 100644 --- a/src/ring_buffer/spsc.rs +++ b/src/ring_buffer/spsc.rs @@ -1,5 +1,5 @@ -use core::ptr::{self, Shared}; use core::marker::{PhantomData, Unsize}; +use core::ptr::{self, Shared}; use BufferFullError; use ring_buffer::RingBuffer; @@ -89,6 +89,10 @@ where let buffer: &mut [T] = unsafe { rb.buffer.as_mut() }; let tail = rb.tail.load_relaxed(); + // NOTE we could replace this `load_acquire` with a `load_relaxed` and this method would be + // sound on most architectures but that change would result in UB according to the C++ + // memory model, which is what Rust currently uses, so we err on the side of caution and + // stick to `load_acquire`. Check issue google#sanitizers#882 for more details. let head = rb.head.load_acquire(); let next_tail = (tail + 1) % n; if next_tail != head { diff --git a/src/vec.rs b/src/vec.rs index 9140cde..e1b91ec 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -37,6 +37,11 @@ where buffer.len() } + /// Clears the vector, removing all values. + pub fn clear(&mut self) { + self.truncate(0); + } + /// 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() }; @@ -67,6 +72,20 @@ where Err(BufferFullError) } } + + /// Shortens the vector, keeping the first `len` elements and dropping the rest. + pub fn truncate(&mut self, len: usize) { + unsafe { + // drop any extra elements + while len < self.len { + // decrement len before the drop_in_place(), so a panic on Drop + // doesn't re-drop the just-failed value. + self.len -= 1; + let len = self.len; + ptr::drop_in_place(self.get_unchecked_mut(len)); + } + } + } } impl<T, A> Drop for Vec<T, A> -- GitLab