RingBuffer: put smaller atomic indices behind a Cargo feature

this let us drop the core_intrinsics feature gate
This commit is contained in:
Jorge Aparicio 2018-07-13 18:51:06 -05:00
parent f1b58a8d67
commit ddc6842342
4 changed files with 70 additions and 15 deletions

View File

@ -19,8 +19,9 @@ repository = "https://github.com/japaric/heapless"
version = "0.3.6" version = "0.3.6"
[features] [features]
default = ["const-fn"] default = ["const-fn", "smaller-atomics"]
const-fn = [] const-fn = []
smaller-atomics = []
[dev-dependencies] [dev-dependencies]
scoped_threadpool = "0.1.8" scoped_threadpool = "0.1.8"

View File

@ -83,7 +83,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(warnings)] #![deny(warnings)]
#![cfg_attr(feature = "const-fn", feature(const_fn))] #![cfg_attr(feature = "const-fn", feature(const_fn))]
#![feature(core_intrinsics)] #![cfg_attr(feature = "smaller-atomics", feature(core_intrinsics))]
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![no_std] #![no_std]

View File

@ -1,8 +1,12 @@
//! Ring buffer //! Ring buffer
use core::cell::UnsafeCell; use core::cell::UnsafeCell;
#[cfg(feature = "smaller-atomics")]
use core::intrinsics;
use core::ops::Add; use core::ops::Add;
use core::{intrinsics, ptr}; use core::ptr;
#[cfg(not(feature = "smaller-atomics"))]
use core::sync::atomic::{AtomicUsize, Ordering};
use generic_array::typenum::{Sum, U1, Unsigned}; use generic_array::typenum::{Sum, U1, Unsigned};
use generic_array::{ArrayLength, GenericArray}; use generic_array::{ArrayLength, GenericArray};
@ -14,12 +18,43 @@ mod spsc;
/// Types that can be used as `RingBuffer` indices: `u8`, `u16` and `usize /// Types that can be used as `RingBuffer` indices: `u8`, `u16` and `usize
/// ///
/// Do not implement this trait yourself /// This trait is sealed and cannot be implemented outside of `heapless`.
pub unsafe trait Uxx: Into<usize> + Send { pub unsafe trait Uxx: Into<usize> + Send {
#[doc(hidden)] #[doc(hidden)]
fn truncate(x: usize) -> Self; fn truncate(x: usize) -> Self;
#[cfg(feature = "smaller-atomics")]
#[doc(hidden)]
fn load_acquire(x: *mut Self) -> Self {
unsafe { intrinsics::atomic_load_acq(x) }
}
#[cfg(not(feature = "smaller-atomics"))]
#[doc(hidden)]
fn load_acquire(x: *mut Self) -> Self;
#[cfg(feature = "smaller-atomics")]
#[doc(hidden)]
fn load_relaxed(x: *mut Self) -> Self {
unsafe { intrinsics::atomic_load_relaxed(x) }
}
#[cfg(not(feature = "smaller-atomics"))]
#[doc(hidden)]
fn load_relaxed(x: *mut Self) -> Self;
#[cfg(feature = "smaller-atomics")]
#[doc(hidden)]
fn store_release(x: *mut Self, val: Self) {
unsafe { intrinsics::atomic_store_rel(x, val) }
}
#[cfg(not(feature = "smaller-atomics"))]
#[doc(hidden)]
fn store_release(x: *mut Self, val: Self);
} }
#[cfg(feature = "smaller-atomics")]
unsafe impl Uxx for u8 { unsafe impl Uxx for u8 {
fn truncate(x: usize) -> Self { fn truncate(x: usize) -> Self {
let max = ::core::u8::MAX; let max = ::core::u8::MAX;
@ -31,6 +66,7 @@ unsafe impl Uxx for u8 {
} }
} }
#[cfg(feature = "smaller-atomics")]
unsafe impl Uxx for u16 { unsafe impl Uxx for u16 {
fn truncate(x: usize) -> Self { fn truncate(x: usize) -> Self {
let max = ::core::u16::MAX; let max = ::core::u16::MAX;
@ -46,6 +82,23 @@ unsafe impl Uxx for usize {
fn truncate(x: usize) -> Self { fn truncate(x: usize) -> Self {
x x
} }
#[cfg(not(feature = "smaller-atomics"))]
fn load_acquire(x: *mut Self) -> Self {
unsafe { (*(x as *mut AtomicUsize)).load(Ordering::Acquire) }
}
#[cfg(not(feature = "smaller-atomics"))]
fn load_relaxed(x: *mut Self) -> Self {
unsafe { (*(x as *mut AtomicUsize)).load(Ordering::Relaxed) }
}
#[cfg(not(feature = "smaller-atomics"))]
fn store_release(x: *mut Self, val: Self) {
unsafe {
(*(x as *mut AtomicUsize)).store(val, Ordering::Release);
}
}
} }
// Atomic{U8,U16, Usize} with no CAS operations that works on targets that have "no atomic support" // Atomic{U8,U16, Usize} with no CAS operations that works on targets that have "no atomic support"
@ -61,28 +114,26 @@ impl<U> Atomic<U>
where where
U: Uxx, U: Uxx,
{ {
const_fn!( const_fn!(const fn new(v: U) -> Atomic<U> {
const fn new(v: U) -> Atomic<U> { Atomic {
Atomic { v: UnsafeCell::new(v),
v: UnsafeCell::new(v),
}
} }
); });
fn get_mut(&mut self) -> &mut U { fn get_mut(&mut self) -> &mut U {
unsafe { &mut *self.v.get() } unsafe { &mut *self.v.get() }
} }
fn load_acquire(&self) -> U { fn load_acquire(&self) -> U {
unsafe { intrinsics::atomic_load_acq(self.v.get()) } U::load_acquire(self.v.get())
} }
fn load_relaxed(&self) -> U { fn load_relaxed(&self) -> U {
unsafe { intrinsics::atomic_load_relaxed(self.v.get()) } U::load_relaxed(self.v.get())
} }
fn store_release(&self, val: U) { fn store_release(&self, val: U) {
unsafe { intrinsics::atomic_store_rel(self.v.get(), val) } U::store_release(self.v.get(), val)
} }
} }
@ -269,7 +320,6 @@ macro_rules! impl_ {
N: Add<U1> + Unsigned, N: Add<U1> + Unsigned,
Sum<N, U1>: ArrayLength<T>, Sum<N, U1>: ArrayLength<T>,
{ {
const_fn!( const_fn!(
/// Creates an empty ring buffer with a fixed capacity of `N` /// Creates an empty ring buffer with a fixed capacity of `N`
pub const fn $uxx() -> Self { pub const fn $uxx() -> Self {
@ -357,7 +407,6 @@ where
N: Add<U1> + Unsigned, N: Add<U1> + Unsigned,
Sum<N, U1>: ArrayLength<T>, Sum<N, U1>: ArrayLength<T>,
{ {
const_fn!( const_fn!(
/// Alias for [`RingBuffer::usize`](struct.RingBuffer.html#method.usize) /// Alias for [`RingBuffer::usize`](struct.RingBuffer.html#method.usize)
pub const fn new() -> Self { pub const fn new() -> Self {
@ -366,7 +415,9 @@ where
); );
} }
#[cfg(feature = "smaller-atomics")]
impl_!(u8); impl_!(u8);
#[cfg(feature = "smaller-atomics")]
impl_!(u16); impl_!(u16);
impl_!(usize); impl_!(usize);
@ -548,6 +599,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(feature = "smaller-atomics")]
fn u8() { fn u8() {
let mut rb: RingBuffer<u8, U256, _> = RingBuffer::u8(); let mut rb: RingBuffer<u8, U256, _> = RingBuffer::u8();

View File

@ -196,7 +196,9 @@ macro_rules! impl_ {
}; };
} }
#[cfg(feature = "smaller-atomics")]
impl_!(u8); impl_!(u8);
#[cfg(feature = "smaller-atomics")]
impl_!(u16); impl_!(u16);
impl_!(usize); impl_!(usize);