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