92: use core::mem::MaybeUninit; drop min-const-fn and smaller-atomics features r=japaric a=japaric

closes #69 

this contains breaking changes (see CHANGELOG) and bumps the crate version to 0.5.0. We'll make a pre-release (i.e. v0.5.0-alpha.1) after rust-lang/rust#60445 lands and a proper release when that PR makes into the stable channel.

Co-authored-by: Jorge Aparicio <jorge@japaric.io>
This commit is contained in:
bors[bot] 2019-05-03 13:58:22 +00:00
commit 91dfd3ccb8
20 changed files with 203 additions and 428 deletions

View File

@ -2,22 +2,10 @@ language: rust
matrix:
include:
# MSRV
- env: TARGET=x86_64-unknown-linux-gnu
rust: 1.30.0
if: branch != master
- env: TARGET=x86_64-unknown-linux-gnu
rust: stable
if: branch != master
- env: TARGET=thumbv6m-none-eabi
rust: beta
if: branch != master
- env: TARGET=thumbv7m-none-eabi
rust: stable
if: branch != master
# TODO MSRV
# - env: TARGET=x86_64-unknown-linux-gnu
# rust: 1.36.0
# if: branch != master
- env: TARGET=x86_64-unknown-linux-gnu
rust: nightly

View File

@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## [v0.5.0] - 2019-06-xx
### Removed
- [breaking-change] The "smaller-atomics" feature has been removed. It is now
always enabled.
- [breaking-change] The "min-const-fn" feature has been removed. It is now
always enabled.
- [breaking-change] The MSRV has been bumped to Rust 1.36.0.
- [breaking-change] The version of the `generic-array` dependency has been
bumped to v0.13.0.
## [v0.4.4] - 2019-05-02
### Added

View File

@ -9,6 +9,7 @@ categories = [
]
description = "`static` friendly data structures that don't require dynamic memory allocation"
documentation = "https://japaric.github.io/heapless/heapless/index.html"
edition = "2018"
keywords = [
"static",
"no-heap",
@ -16,19 +17,17 @@ keywords = [
license = "MIT OR Apache-2.0"
name = "heapless"
repository = "https://github.com/japaric/heapless"
version = "0.4.4"
version = "0.5.0-alpha.1"
[features]
const-fn = ["min-const-fn"]
min-const-fn = []
smaller-atomics = []
const-fn = []
[dev-dependencies]
scoped_threadpool = "0.1.8"
[dependencies]
as-slice = "0.1.0"
generic-array = "0.11.0"
generic-array = "0.13.0"
hash32 = "0.1.0"
[dependencies.serde]
@ -37,4 +36,4 @@ optional = true
default-features = false
[package.metadata.docs.rs]
features = ["const-fn", "smaller-atomics"]
features = ["const-fn"]

View File

@ -3,7 +3,7 @@ set -euxo pipefail
main() {
cargo check --target $TARGET --features 'serde'
if [ $TRAVIS_RUST_VERSION = nightly ]; then
cargo check --target $TARGET --features 'const-fn smaller-atomics'
cargo check --target $TARGET --features 'const-fn'
fi
if [ $TARGET = x86_64-unknown-linux-gnu ]; then
@ -11,17 +11,17 @@ main() {
cargo test --target $TARGET --release --features 'serde'
if [ $TRAVIS_RUST_VERSION = nightly ]; then
cargo test --target $TARGET --features 'const-fn smaller-atomics'
cargo test --target $TARGET --release --features 'const-fn smaller-atomics'
cargo test --target $TARGET --features 'const-fn'
cargo test --target $TARGET --release --features 'const-fn'
export RUSTFLAGS="-Z sanitizer=thread"
export RUST_TEST_THREADS=1
export TSAN_OPTIONS="suppressions=$(pwd)/blacklist.txt"
cargo test --test tsan --target $TARGET
cargo test --test tsan --target $TARGET --features 'const-fn smaller-atomics'
cargo test --test tsan --target $TARGET --features 'const-fn'
cargo test --test tsan --target $TARGET --release
cargo test --test tsan --target $TARGET --release --features 'const-fn smaller-atomics'
cargo test --test tsan --target $TARGET --release --features 'const-fn'
fi
fi
}

View File

@ -1,54 +0,0 @@
/// Temporary fork of some stuff in `core` that's doesn't have a `const fn` API
pub mod mem {
#[cfg(not(feature = "const-fn"))]
pub use core::mem;
pub use core::mem::{replace, zeroed, ManuallyDrop};
// See RFC 1892
#[cfg(feature = "const-fn")]
pub union MaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
}
// workaround to get this to compile on stable ("unions with non-`Copy` fields are unstable")
#[cfg(not(feature = "const-fn"))]
pub struct MaybeUninit<T> {
value: ManuallyDrop<T>,
}
impl<T> MaybeUninit<T> {
#[cfg(feature = "const-fn")]
pub const unsafe fn uninitialized() -> Self {
MaybeUninit { uninit: () }
}
#[cfg(not(feature = "const-fn"))]
pub unsafe fn uninitialized() -> Self {
MaybeUninit {
value: ManuallyDrop::new(mem::uninitialized()),
}
}
/// Get a reference to the contained value.
///
/// # Unsafety
///
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an
/// initialized state, otherwise this will immediately cause undefined behavior.
pub unsafe fn get_ref(&self) -> &T {
&*self.value
}
/// Get a mutable reference to the contained value.
///
/// # Unsafety
///
/// It is up to the caller to guarantee that the the `MaybeUninit` really is in an
/// initialized state, otherwise this will immediately cause undefined behavior.
pub unsafe fn get_mut(&mut self) -> &mut T {
&mut *self.value
}
}
}

View File

@ -8,14 +8,17 @@
// heap can also be converted to a sorted vector in-place, allowing it to be used for an `O(n log
// n)` in-place heapsort.
use core::cmp::Ordering;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::{mem, ptr, slice, fmt};
use core::{
cmp::Ordering,
fmt,
marker::PhantomData,
mem::{self, ManuallyDrop},
ptr, slice,
};
use generic_array::ArrayLength;
use Vec;
use crate::Vec;
/// Min-heap
pub enum Min {}
@ -206,7 +209,7 @@ where
///
/// }
/// ```
pub fn iter(&self) -> slice::Iter<T> {
pub fn iter(&self) -> slice::Iter<'_, T> {
self.data.iter()
}
@ -214,7 +217,7 @@ where
///
/// **WARNING** Mutating the items in the binary heap can leave the heap in an inconsistent
/// state.
pub fn iter_mut(&mut self) -> slice::IterMut<T> {
pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
self.data.iter_mut()
}
@ -344,7 +347,7 @@ where
/// (because it was moved from or duplicated).
/// In drop, `Hole` will restore the slice by filling the hole
/// position with the value that was originally removed.
struct Hole<'a, T: 'a> {
struct Hole<'a, T> {
data: &'a mut [T],
/// `elt` is always `Some` from new until drop.
elt: ManuallyDrop<T>,
@ -441,9 +444,9 @@ impl<T, N, K> fmt::Debug for BinaryHeap<T, N, K>
where
N: ArrayLength<T>,
K: Kind,
T: Ord + fmt::Debug
T: Ord + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
@ -466,8 +469,10 @@ where
mod tests {
use std::vec::Vec;
use binary_heap::{self, BinaryHeap, Min};
use consts::*;
use crate::{
binary_heap::{self, BinaryHeap, Min},
consts::*,
};
#[cfg(feature = "const-fn")]
#[test]

View File

@ -33,36 +33,3 @@ macro_rules! const_fn {
fn $($f)*
);
}
#[cfg(not(armv6m))]
macro_rules! min_const_fn {
($(#[$attr:meta])* pub const unsafe fn $($f:tt)*) => (
$(#[$attr])*
#[cfg(feature = "min-const-fn")]
pub const unsafe fn $($f)*
$(#[$attr])*
#[cfg(not(feature = "min-const-fn"))]
pub unsafe fn $($f)*
);
($(#[$attr:meta])* pub const fn $($f:tt)*) => (
$(#[$attr])*
#[cfg(feature = "min-const-fn")]
pub const fn $($f)*
$(#[$attr])*
#[cfg(not(feature = "min-const-fn"))]
pub fn $($f)*
);
($(#[$attr:meta])* const fn $($f:tt)*) => (
$(#[$attr])*
#[cfg(feature = "min-const-fn")]
const fn $($f)*
$(#[$attr])*
#[cfg(not(feature = "min-const-fn"))]
fn $($f)*
);
}

View File

@ -1,18 +1,14 @@
use core::fmt;
use core::marker::PhantomData;
use core::{fmt, marker::PhantomData};
use generic_array::{typenum::PowerOfTwo, ArrayLength};
use hash32::{BuildHasherDefault, Hash, Hasher};
use serde::de::{self, Deserialize, Deserializer, Error, MapAccess, SeqAccess};
use super::binary_heap::Kind as BinaryHeapKind;
use super::indexmap::{Bucket, Pos};
use BinaryHeap;
use IndexMap;
use IndexSet;
use LinearMap;
use String;
use Vec;
use crate::{
binary_heap,
indexmap::{Bucket, Pos},
BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
};
// Sequential containers
@ -20,7 +16,7 @@ impl<'de, T, N, KIND> Deserialize<'de> for BinaryHeap<T, N, KIND>
where
T: Ord + Deserialize<'de>,
N: ArrayLength<T>,
KIND: BinaryHeapKind,
KIND: binary_heap::Kind,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@ -32,11 +28,11 @@ where
where
T: Ord + Deserialize<'de>,
N: ArrayLength<T>,
KIND: BinaryHeapKind,
KIND: binary_heap::Kind,
{
type Value = BinaryHeap<T, N, KIND>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
@ -79,7 +75,7 @@ where
{
type Value = IndexSet<T, N, BuildHasherDefault<S>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
@ -120,7 +116,7 @@ where
{
type Value = Vec<T, N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a sequence")
}
@ -167,7 +163,7 @@ where
{
type Value = IndexMap<K, V, N, BuildHasherDefault<S>>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a map")
}
@ -210,7 +206,7 @@ where
{
type Value = LinearMap<K, V, N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a map")
}
@ -251,7 +247,7 @@ where
{
type Value = String<N>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
formatter,
"a string no more than {} bytes long",

View File

@ -1,15 +1,16 @@
use core::borrow::Borrow;
use core::iter::FromIterator;
use core::num::NonZeroU32;
use core::{fmt, ops, slice};
use generic_array::typenum::PowerOfTwo;
use generic_array::{ArrayLength, GenericArray};
use core::{
borrow::Borrow,
fmt,
iter::FromIterator,
mem::{self, MaybeUninit},
num::NonZeroU32,
ops, slice,
};
use generic_array::{typenum::PowerOfTwo, ArrayLength, GenericArray};
use hash32::{BuildHasher, BuildHasherDefault, FnvHasher, Hash, Hasher};
use Vec;
use __core::mem;
use crate::Vec;
/// An `IndexMap` using the default FNV hasher
pub type FnvIndexMap<K, V, N> = IndexMap<K, V, N, BuildHasherDefault<FnvHasher>>;
@ -102,7 +103,7 @@ where
fn new() -> Self {
CoreMap {
entries: Vec::new(),
indices: unsafe { mem::zeroed() },
indices: unsafe { MaybeUninit::zeroed().assume_init() },
}
}
@ -440,7 +441,7 @@ where
/// println!("key: {} val: {}", key, val);
/// }
/// ```
pub fn iter(&self) -> Iter<K, V> {
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
iter: self.core.entries.iter(),
}
@ -465,7 +466,7 @@ where
/// println!("key: {} val: {}", key, val);
/// }
/// ```
pub fn iter_mut(&mut self) -> IterMut<K, V> {
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut {
iter: self.core.entries.iter_mut(),
}
@ -762,7 +763,7 @@ where
S: BuildHasher,
N: ArrayLength<Bucket<K, V>> + ArrayLength<Option<Pos>>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
@ -805,10 +806,8 @@ where
S: BuildHasher,
N: ArrayLength<Bucket<K, V>> + ArrayLength<Option<Pos>>,
{
}
impl<K, V, N, S> Extend<(K, V)> for IndexMap<K, V, N, S>
where
K: Eq + Hash,
@ -884,19 +883,11 @@ where
}
}
pub struct Iter<'a, K, V>
where
K: 'a,
V: 'a,
{
pub struct Iter<'a, K, V> {
iter: slice::Iter<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V>
where
K: 'a,
V: 'a,
{
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
@ -904,11 +895,7 @@ where
}
}
impl<'a, K, V> Clone for Iter<'a, K, V>
where
K: 'a,
V: 'a,
{
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
@ -916,19 +903,11 @@ where
}
}
pub struct IterMut<'a, K, V>
where
K: 'a,
V: 'a,
{
pub struct IterMut<'a, K, V> {
iter: slice::IterMut<'a, Bucket<K, V>>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V>
where
K: 'a,
V: 'a,
{
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<Self::Item> {
@ -954,8 +933,7 @@ mod tests {
use generic_array::typenum::Unsigned;
use consts::*;
use FnvIndexMap;
use crate::{consts::*, FnvIndexMap};
#[test]
fn size() {
@ -973,14 +951,13 @@ mod tests {
)
}
#[test]
fn partial_eq() {
{
let mut a: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
a.insert("k1", "v1").unwrap();
let mut b: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
let mut b: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
b.insert("k1", "v1").unwrap();
assert!(a == b);
@ -991,11 +968,11 @@ mod tests {
}
{
let mut a: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
let mut a: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
a.insert("k1", "v1").unwrap();
a.insert("k2", "v2").unwrap();
let mut b: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
let mut b: FnvIndexMap<_, _, U4> = FnvIndexMap::new();
b.insert("k2", "v2").unwrap();
b.insert("k1", "v1").unwrap();

View File

@ -1,12 +1,9 @@
use core::borrow::Borrow;
use core::fmt;
use core::iter::FromIterator;
use core::{borrow::Borrow, fmt, iter::FromIterator};
use generic_array::typenum::PowerOfTwo;
use generic_array::ArrayLength;
use generic_array::{typenum::PowerOfTwo, ArrayLength};
use hash32::{BuildHasher, BuildHasherDefault, FnvHasher, Hash, Hasher};
use indexmap::{self, Bucket, IndexMap, Pos};
use crate::indexmap::{self, Bucket, IndexMap, Pos};
/// An `IndexSet` using the default FNV hasher
pub type FnvIndexSet<T, N> = IndexSet<T, N, BuildHasherDefault<FnvHasher>>;
@ -104,7 +101,7 @@ where
/// println!("{}", x);
/// }
/// ```
pub fn iter(&self) -> Iter<T> {
pub fn iter(&self) -> Iter<'_, T> {
Iter {
iter: self.map.iter(),
}
@ -473,7 +470,7 @@ where
S: BuildHasher,
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
@ -562,17 +559,11 @@ where
}
}
pub struct Iter<'a, T>
where
T: 'a,
{
pub struct Iter<'a, T> {
iter: indexmap::Iter<'a, T, ()>,
}
impl<'a, T> Iterator for Iter<'a, T>
where
T: 'a,
{
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
@ -580,10 +571,7 @@ where
}
}
impl<'a, T> Clone for Iter<'a, T>
where
T: 'a,
{
impl<'a, T> Clone for Iter<'a, T> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
@ -593,9 +581,9 @@ where
pub struct Difference<'a, T, N, S>
where
S: 'a + BuildHasher,
T: 'a + Eq + Hash,
N: 'a + ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
S: BuildHasher,
T: Eq + Hash,
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
{
iter: Iter<'a, T>,
other: &'a IndexSet<T, N, S>,
@ -603,9 +591,9 @@ where
impl<'a, T, N, S> Iterator for Difference<'a, T, N, S>
where
S: 'a + BuildHasher,
T: 'a + Eq + Hash,
N: 'a + ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
S: BuildHasher,
T: Eq + Hash,
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
{
type Item = &'a T;
@ -621,9 +609,9 @@ where
pub struct Intersection<'a, T, N, S>
where
S: 'a + BuildHasher,
T: 'a + Eq + Hash,
N: 'a + ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
S: BuildHasher,
T: Eq + Hash,
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
{
iter: Iter<'a, T>,
other: &'a IndexSet<T, N, S>,
@ -631,9 +619,9 @@ where
impl<'a, T, N, S> Iterator for Intersection<'a, T, N, S>
where
S: 'a + BuildHasher,
T: 'a + Eq + Hash,
N: 'a + ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
S: BuildHasher,
T: Eq + Hash,
N: ArrayLength<Bucket<T, ()>> + ArrayLength<Option<Pos>>,
{
type Item = &'a T;

View File

@ -57,7 +57,7 @@
//!
//! # Minimum Supported Rust Version (MSRV)
//!
//! This crate is guaranteed to compile on stable Rust 1.30 and up with its default set of features.
//! This crate is guaranteed to compile on stable Rust 1.36 and up with its default set of features.
//! It *might* compile on older versions but that may change in any new patch release.
//!
//! # Cargo features
@ -79,28 +79,14 @@
//!
//! - `"const-fn"` -- Enables the nightly `const_fn` and `untagged_unions` features and makes most
//! `new` methods `const`. This way they can be used to initialize static memory at compile time.
//!
//! - `"min-const-fn"` -- Turns `Pool::new` into a const fn and makes the `pool!` macro available.
//! This bumps the required Rust version to 1.31.0.
//!
//! - `"smaller-atomics"` -- Lets you initialize `spsc::Queue`s with smaller head / tail indices
//! (they default to `usize`), shrinking the overall size of the queue.
#![allow(warnings)]
#![deny(missing_docs)]
#![deny(warnings)]
#![cfg_attr(feature = "const-fn", feature(const_fn))]
#![cfg_attr(feature = "const-fn", feature(untagged_unions))]
#![no_std]
extern crate as_slice;
extern crate generic_array;
extern crate hash32;
#[cfg(test)]
extern crate std;
#[cfg(feature = "serde")]
extern crate serde;
#![cfg_attr(not(test), no_std)]
#![deny(missing_docs)]
#![deny(rust_2018_compatibility)]
#![deny(rust_2018_idioms)]
#![deny(warnings)]
#![feature(maybe_uninit)]
#[macro_use]
mod const_fn;
@ -131,5 +117,4 @@ pub mod binary_heap;
pub mod pool;
pub mod spsc;
mod __core;
mod sealed;

View File

@ -1,10 +1,8 @@
use core::borrow::Borrow;
use core::{mem, ops, slice, fmt};
use core::iter::FromIterator;
use core::{borrow::Borrow, fmt, iter::FromIterator, mem, ops, slice};
use generic_array::ArrayLength;
use Vec;
use crate::Vec;
/// A fixed capacity map / dictionary that performs lookups via linear search
///
@ -232,7 +230,7 @@ where
/// println!("key: {} val: {}", key, val);
/// }
/// ```
pub fn iter(&self) -> Iter<K, V> {
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
iter: self.buffer.iter(),
}
@ -261,7 +259,7 @@ where
/// println!("key: {} val: {}", key, val);
/// }
/// ```
pub fn iter_mut(&mut self) -> IterMut<K, V> {
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
IterMut {
iter: self.buffer.iter_mut(),
}
@ -370,7 +368,6 @@ where
N: ArrayLength<(K, V)>,
K: Borrow<Q> + Eq,
Q: Eq + ?Sized,
V: 'a,
{
type Output = V;
@ -384,7 +381,6 @@ where
N: ArrayLength<(K, V)>,
K: Borrow<Q> + Eq,
Q: Eq + ?Sized,
V: 'a,
{
fn index_mut(&mut self, key: &Q) -> &mut V {
self.get_mut(key).expect("no entry found for key")
@ -420,7 +416,7 @@ where
K: Eq + fmt::Debug,
V: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.iter()).finish()
}
}
@ -487,19 +483,11 @@ where
}
}
pub struct Iter<'a, K, V>
where
K: 'a,
V: 'a,
{
pub struct Iter<'a, K, V> {
iter: slice::Iter<'a, (K, V)>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V>
where
K: 'a,
V: 'a,
{
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<Self::Item> {
@ -507,11 +495,7 @@ where
}
}
impl<'a, K, V> Clone for Iter<'a, K, V>
where
K: 'a,
V: 'a,
{
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
@ -519,19 +503,11 @@ where
}
}
pub struct IterMut<'a, K, V>
where
K: 'a,
V: 'a,
{
pub struct IterMut<'a, K, V> {
iter: slice::IterMut<'a, (K, V)>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V>
where
K: 'a,
V: 'a,
{
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<Self::Item> {
@ -562,11 +538,9 @@ where
{
}
#[cfg(feature = "const-fn")] // Remove this if there are more tests
#[cfg(test)]
mod test {
use consts::*;
use LinearMap;
use crate::{consts::*, LinearMap};
#[cfg(feature = "const-fn")]
#[test]

View File

@ -159,7 +159,6 @@ use core::{
ptr::{self, NonNull},
sync::atomic::AtomicPtr,
};
#[cfg(not(armv6m))]
use core::{any::TypeId, mem, sync::atomic::Ordering};
@ -185,14 +184,12 @@ unsafe impl<T> Sync for Pool<T> {}
unsafe impl<T> Send for Pool<T> {}
impl<T> Pool<T> {
min_const_fn! {
/// Creates a new empty pool
pub const fn new() -> Self {
Pool {
head: AtomicPtr::new(ptr::null_mut()),
/// Creates a new empty pool
pub const fn new() -> Self {
Pool {
head: AtomicPtr::new(ptr::null_mut()),
_not_send_or_sync: PhantomData,
}
_not_send_or_sync: PhantomData,
}
}
@ -386,7 +383,7 @@ impl<T> fmt::Debug for Box<T>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as fmt::Debug>::fmt(self, f)
}
}
@ -395,7 +392,7 @@ impl<T> fmt::Display for Box<T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<T as fmt::Display>::fmt(self, f)
}
}
@ -454,13 +451,8 @@ mod tests {
fn grow() {
static mut MEMORY: [u8; 1024] = [0; 1024];
#[cfg(feature = "min-const-fn")]
static POOL: Pool<[u8; 128]> = Pool::new();
#[allow(non_snake_case)]
#[cfg(not(feature = "min-const-fn"))]
let POOL: Pool<[u8; 128]> = Pool::new();
unsafe {
POOL.grow(&mut MEMORY);
}
@ -474,13 +466,8 @@ mod tests {
fn sanity() {
static mut MEMORY: [u8; 31] = [0; 31];
#[cfg(feature = "min-const-fn")]
static POOL: Pool<u8> = Pool::new();
#[allow(non_snake_case)]
#[cfg(not(feature = "min-const-fn"))]
let POOL: Pool<u8> = Pool::new();
// empty pool
assert!(POOL.alloc().is_none());
@ -519,13 +506,8 @@ mod tests {
static mut MEMORY: [u8; 31] = [0; 31];
#[cfg(feature = "min-const-fn")]
static POOL: Pool<X> = Pool::new();
#[allow(non_snake_case)]
#[cfg(not(feature = "min-const-fn"))]
let POOL: Pool<X> = Pool::new();
POOL.grow(unsafe { &mut MEMORY });
let x = POOL.alloc().unwrap().init(X::new());

View File

@ -15,7 +15,7 @@ use as_slice::{AsMutSlice, AsSlice};
use super::{Init, Uninit};
/// Instantiates a pool as a global singleton
#[cfg(all(any(armv7m, test), feature = "min-const-fn"))]
#[cfg(any(armv7m, test))]
#[macro_export]
macro_rules! pool {
($ident:ident: $ty:ty) => {
@ -153,7 +153,7 @@ where
P: Pool,
P::Data: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<P::Data as fmt::Debug>::fmt(self, f)
}
}
@ -163,7 +163,7 @@ where
P: Pool,
P::Data: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<P::Data as fmt::Display>::fmt(self, f)
}
}
@ -270,7 +270,7 @@ where
}
}
#[cfg(all(test, feature = "min-const-fn"))]
#[cfg(test)]
mod tests {
use core::{
mem,

View File

@ -1,8 +1,6 @@
use core::sync::atomic::{self, AtomicUsize, Ordering};
#[cfg(feature = "smaller-atomics")]
use core::sync::atomic::{AtomicU16, AtomicU8};
use core::sync::atomic::{self, AtomicU16, AtomicU8, AtomicUsize, Ordering};
use spsc::{MultiCore, SingleCore};
use crate::spsc::{MultiCore, SingleCore};
pub unsafe trait XCore {
fn is_multi_core() -> bool;
@ -38,7 +36,6 @@ pub unsafe trait Uxx: Into<usize> + Send {
C: XCore;
}
#[cfg(feature = "smaller-atomics")]
unsafe impl Uxx for u8 {
fn truncate(x: usize) -> Self {
let max = ::core::u8::MAX;
@ -79,7 +76,6 @@ unsafe impl Uxx for u8 {
}
}
#[cfg(feature = "smaller-atomics")]
unsafe impl Uxx for u16 {
fn truncate(x: usize) -> Self {
let max = ::core::u16::MAX;

View File

@ -1,16 +1,12 @@
use hash32::{BuildHasher, Hash};
use generic_array::{typenum::PowerOfTwo, ArrayLength};
use hash32::{BuildHasher, Hash};
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
use super::binary_heap::Kind as BinaryHeapKind;
use super::indexmap::{Bucket, Pos};
use BinaryHeap;
use IndexMap;
use IndexSet;
use LinearMap;
use String;
use Vec;
use crate::{
binary_heap::Kind as BinaryHeapKind,
indexmap::{Bucket, Pos},
BinaryHeap, IndexMap, IndexSet, LinearMap, String, Vec,
};
// Sequential containers

View File

@ -1,15 +1,12 @@
//! Single producer single consumer queue
use core::cell::UnsafeCell;
use core::marker::PhantomData;
use core::{ptr, fmt, hash};
use core::{cell::UnsafeCell, fmt, hash, marker::PhantomData, mem::MaybeUninit, ptr};
use generic_array::{ArrayLength, GenericArray};
use hash32;
pub use self::split::{Consumer, Producer};
use __core::mem::MaybeUninit;
use sealed;
use crate::sealed;
pub use split::{Consumer, Producer};
mod split;
@ -176,7 +173,7 @@ where
}
/// Iterates from the front of the queue to the back
pub fn iter(&self) -> Iter<T, N, U, C> {
pub fn iter(&self) -> Iter<'_, T, N, U, C> {
Iter {
rb: self,
index: 0,
@ -185,7 +182,7 @@ where
}
/// Returns an iterator that allows modifying each value.
pub fn iter_mut(&mut self) -> IterMut<T, N, U, C> {
pub fn iter_mut(&mut self) -> IterMut<'_, T, N, U, C> {
let len = self.len_usize();
IterMut {
rb: self,
@ -224,7 +221,7 @@ where
U: sealed::Uxx,
C: sealed::XCore,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
@ -259,7 +256,6 @@ where
}
}
impl<'a, T, N, U, C> IntoIterator for &'a Queue<T, N, U, C>
where
N: ArrayLength<T>,
@ -298,7 +294,7 @@ macro_rules! impl_ {
/// Creates an empty queue with a fixed capacity of `N`
pub const fn $uxx() -> Self {
Queue {
buffer: unsafe { MaybeUninit::uninitialized() },
buffer: MaybeUninit::uninit(),
head: Atomic::new(0),
tail: Atomic::new(0),
}
@ -314,7 +310,7 @@ macro_rules! impl_ {
/// Creates an empty queue with a fixed capacity of `N` (single core variant)
pub const unsafe fn $uxx_sc() -> Self {
Queue {
buffer: MaybeUninit::uninitialized(),
buffer: MaybeUninit::uninit(),
head: Atomic::new(0),
tail: Atomic::new(0),
}
@ -334,10 +330,10 @@ macro_rules! impl_ {
let head = self.head.get_mut();
let tail = self.tail.get_mut();
let buffer = unsafe { self.buffer.get_ref() };
let p = self.buffer.as_ptr();
if *head != *tail {
let item = unsafe { ptr::read(buffer.get_unchecked(usize::from(*head % cap))) };
let item = unsafe { (p as *const T).add(usize::from(*head % cap)).read() };
*head = head.wrapping_add(1);
Some(item)
} else {
@ -373,12 +369,12 @@ macro_rules! impl_ {
let cap = self.capacity();
let tail = self.tail.get_mut();
let buffer = self.buffer.get_mut();
// 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
ptr::write(buffer.get_unchecked_mut(usize::from(*tail % cap)), item);
(self.buffer.as_mut_ptr() as *mut T)
.add(usize::from(*tail % cap))
.write(item);
*tail = tail.wrapping_add(1);
}
@ -403,7 +399,7 @@ macro_rules! impl_ {
{
fn clone(&self) -> Self {
let mut new: Queue<T, N, $uxx, C> = Queue {
buffer: unsafe { MaybeUninit::uninitialized() },
buffer: MaybeUninit::uninit(),
head: Atomic::new(0),
tail: Atomic::new(0),
};
@ -417,7 +413,6 @@ macro_rules! impl_ {
new
}
}
};
}
@ -445,9 +440,7 @@ where
}
}
#[cfg(feature = "smaller-atomics")]
impl_!(u8, u8_sc);
#[cfg(feature = "smaller-atomics")]
impl_!(u16, u16_sc);
impl_!(usize, usize_sc);
@ -463,10 +456,7 @@ where
{
fn eq(&self, other: &Queue<T, N2, U2, C2>) -> bool {
self.len_usize() == other.len_usize()
&& self
.iter()
.zip(other.iter())
.all(|(v1, v2)| v1 == v2)
&& self.iter().zip(other.iter()).all(|(v1, v2)| v1 == v2)
}
}
@ -477,16 +467,14 @@ where
U: sealed::Uxx,
C: sealed::XCore,
{
}
/// An iterator over the items of a queue
pub struct Iter<'a, T, N, U, C>
where
N: ArrayLength<T> + 'a,
T: 'a,
U: 'a + sealed::Uxx,
C: 'a + sealed::XCore,
N: ArrayLength<T>,
U: sealed::Uxx,
C: sealed::XCore,
{
rb: &'a Queue<T, N, U, C>,
index: usize,
@ -495,10 +483,9 @@ where
impl<'a, T, N, U, C> Clone for Iter<'a, T, N, U, C>
where
N: ArrayLength<T> + 'a,
T: 'a,
U: 'a + sealed::Uxx,
C: 'a + sealed::XCore,
N: ArrayLength<T>,
U: sealed::Uxx,
C: sealed::XCore,
{
fn clone(&self) -> Self {
Self {
@ -512,10 +499,9 @@ where
/// A mutable iterator over the items of a queue
pub struct IterMut<'a, T, N, U, C>
where
N: ArrayLength<T> + 'a,
T: 'a,
U: 'a + sealed::Uxx,
C: 'a + sealed::XCore,
N: ArrayLength<T>,
U: sealed::Uxx,
C: sealed::XCore,
{
rb: &'a mut Queue<T, N, U, C>,
index: usize,
@ -523,13 +509,12 @@ where
}
macro_rules! iterator {
(struct $name:ident -> $elem:ty, $ptr:ty, $asref:ident, $asptr:ident, $mkref:ident) => {
(struct $name:ident -> $elem:ty, $ptr:ty, $asptr:ident, $mkref:ident) => {
impl<'a, T, N, U, C> Iterator for $name<'a, T, N, U, C>
where
N: ArrayLength<T>,
T: 'a,
U: 'a + sealed::Uxx,
C: 'a + sealed::XCore,
U: sealed::Uxx,
C: sealed::XCore,
{
type Item = $elem;
@ -538,8 +523,7 @@ macro_rules! iterator {
let head = self.rb.head.load_relaxed().into();
let cap = self.rb.capacity().into();
let buffer = unsafe { self.rb.buffer.$asref() };
let ptr: $ptr = buffer.$asptr();
let ptr = self.rb.buffer.$asptr() as $ptr;
let i = (head + self.index) % cap;
self.index += 1;
Some(unsafe { $mkref!(*ptr.offset(i as isize)) })
@ -563,15 +547,15 @@ macro_rules! make_ref_mut {
};
}
iterator!(struct Iter -> &'a T, *const T, get_ref, as_ptr, make_ref);
iterator!(struct IterMut -> &'a mut T, *mut T, get_mut, as_mut_ptr, make_ref_mut);
iterator!(struct Iter -> &'a T, *const T, as_ptr, make_ref);
iterator!(struct IterMut -> &'a mut T, *mut T, as_mut_ptr, make_ref_mut);
#[cfg(test)]
mod tests {
use consts::*;
use spsc::Queue;
use hash32::Hasher;
use crate::{consts::*, spsc::Queue};
#[cfg(feature = "const-fn")]
#[test]
fn static_new() {
@ -741,11 +725,7 @@ mod tests {
let rb2 = rb1.clone();
assert_eq!(rb1.capacity(), rb2.capacity());
assert_eq!(rb1.len_usize(), rb2.len_usize());
assert!(
rb1.iter()
.zip(rb2.iter())
.all(|(v1, v2)| v1 == v2)
);
assert!(rb1.iter().zip(rb2.iter()).all(|(v1, v2)| v1 == v2));
}
#[test]

View File

@ -1,10 +1,11 @@
use core::marker::PhantomData;
use core::ptr::{self, NonNull};
use core::{marker::PhantomData, ptr::NonNull};
use generic_array::ArrayLength;
use sealed;
use spsc::{MultiCore, Queue};
use crate::{
sealed,
spsc::{MultiCore, Queue},
};
impl<T, N, U, C> Queue<T, N, U, C>
where
@ -110,9 +111,10 @@ macro_rules! impl_ {
let rb = self.rb.as_ref();
let cap = rb.capacity();
let buffer = rb.buffer.get_ref();
let item = ptr::read(buffer.get_unchecked(usize::from(head % cap)));
let item = (rb.buffer.as_ptr() as *const T)
.add(usize::from(head % cap))
.read();
rb.head.store_release(head.wrapping_add(1)); // ▲
item
}
@ -177,28 +179,26 @@ macro_rules! impl_ {
let rb = self.rb.as_mut();
let cap = rb.capacity();
let buffer = rb.buffer.get_mut();
// 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
ptr::write(buffer.get_unchecked_mut(usize::from(tail % cap)), item);
(rb.buffer.as_mut_ptr() as *mut T)
.add(usize::from(tail % cap))
.write(item);
rb.tail.store_release(tail.wrapping_add(1)); // ▲
}
}
};
}
#[cfg(feature = "smaller-atomics")]
impl_!(u8);
#[cfg(feature = "smaller-atomics")]
impl_!(u16);
impl_!(usize);
#[cfg(test)]
mod tests {
use consts::*;
use spsc::Queue;
use crate::{consts::*, spsc::Queue};
#[test]
fn sanity() {

View File

@ -1,15 +1,12 @@
use core::fmt::Write;
use core::str::Utf8Error;
use core::{fmt, hash, ops, str};
use hash32;
use core::{fmt, fmt::Write, hash, ops, str, str::Utf8Error};
use generic_array::{
typenum::{consts::*, IsGreaterOrEqual},
ArrayLength,
};
use hash32;
use Vec;
use crate::Vec;
/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html)
pub struct String<N>
@ -444,7 +441,7 @@ impl<N> fmt::Debug for String<N>
where
N: ArrayLength<u8>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let slice: &str = &**self;
fmt::Debug::fmt(slice, f)
}
@ -454,7 +451,7 @@ impl<N> fmt::Display for String<N>
where
N: ArrayLength<u8>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let slice: &str = &**self;
fmt::Display::fmt(slice, f)
}
@ -611,8 +608,7 @@ impl_from_num!(u64, U20);
#[cfg(test)]
mod tests {
use consts::*;
use {String, Vec};
use crate::{consts::*, String, Vec};
#[cfg(feature = "const-fn")]
#[test]
@ -632,8 +628,6 @@ mod tests {
#[test]
fn debug() {
extern crate std;
use core::fmt::Write;
let s: String<U8> = String::from("abcd");
@ -644,8 +638,6 @@ mod tests {
#[test]
fn display() {
extern crate std;
use core::fmt::Write;
let s: String<U8> = String::from("abcd");

View File

@ -1,13 +1,8 @@
use core::{fmt, ops, ptr, slice};
use core::{fmt, hash, iter::FromIterator, mem::MaybeUninit, ops, ptr, slice};
use generic_array::{ArrayLength, GenericArray};
use hash32;
use __core::mem::MaybeUninit;
use core::hash;
use core::iter::FromIterator;
/// A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html)
///
/// # Examples
@ -66,7 +61,7 @@ where
/// Constructs a new, empty vector with a fixed capacity of `N`
pub const fn new() -> Self {
Vec {
buffer: unsafe { MaybeUninit::uninitialized() },
buffer: MaybeUninit::uninit(),
len: 0,
}
}
@ -126,11 +121,8 @@ where
pub(crate) unsafe fn pop_unchecked(&mut self) -> T {
debug_assert!(!self.is_empty());
let buffer = self.buffer.get_ref();
self.len -= 1;
let item = ptr::read(buffer.get_unchecked(self.len));
item
(self.buffer.as_ptr() as *const T).add(self.len).read()
}
/// Appends an `item` to the back of the collection
@ -146,11 +138,12 @@ where
}
pub(crate) unsafe fn push_unchecked(&mut self, item: T) {
let buffer = self.buffer.get_mut();
// 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
ptr::write(buffer.get_unchecked_mut(self.len), item);
(self.buffer.as_mut_ptr() as *mut T)
.add(self.len)
.write(item);
self.len += 1;
}
@ -271,7 +264,7 @@ where
T: fmt::Debug,
N: ArrayLength<T>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let slice: &[T] = &**self;
slice.fmt(f)
}
@ -394,8 +387,7 @@ where
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.next < self.vec.len() {
let buffer = unsafe { self.vec.buffer.get_ref() };
let item = unsafe { ptr::read(buffer.get_unchecked(self.next)) };
let item = unsafe { (self.vec.buffer.as_ptr() as *const T).add(self.next).read() };
self.next += 1;
Some(item)
} else {
@ -500,10 +492,9 @@ where
type Target = [T];
fn deref(&self) -> &[T] {
let buffer = unsafe { self.buffer.get_ref() };
// NOTE(unsafe) avoid bound checks in the slicing operation
// &buffer[..self.len]
unsafe { slice::from_raw_parts(buffer.as_ptr(), self.len) }
unsafe { slice::from_raw_parts(self.buffer.as_ptr() as *const T, self.len) }
}
}
@ -513,11 +504,10 @@ where
{
fn deref_mut(&mut self) -> &mut [T] {
let len = self.len();
let buffer = unsafe { self.buffer.get_mut() };
// NOTE(unsafe) avoid bound checks in the slicing operation
// &mut buffer[..len]
unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr(), len) }
unsafe { slice::from_raw_parts_mut(self.buffer.as_mut_ptr() as *mut T, len) }
}
}
@ -563,8 +553,7 @@ where
#[cfg(test)]
mod tests {
use consts::*;
use Vec;
use crate::{consts::*, Vec};
#[cfg(feature = "const-fn")]
#[test]