From 7936744b2dc7787e4290ab9dfe2fc0d6b144b27a Mon Sep 17 00:00:00 2001 From: Alexey Gerasev Date: Sun, 3 Mar 2024 11:22:24 +0700 Subject: [PATCH] Provide const constructor for array rb --- Cargo.toml | 4 ++-- src/rb/local.rs | 7 ++++--- src/rb/macros.rs | 7 ++++++- src/rb/shared.rs | 5 +++-- src/storage.rs | 5 +++++ src/tests/new.rs | 3 +++ src/utils.rs | 21 ++++++++++----------- 7 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 90d3f32..94d5fdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,14 +7,14 @@ readme = "README.md" license = "MIT/Apache-2.0" [workspace.dependencies] -ringbuf = { path = ".", version = "0.4.0-rc.2" } +ringbuf = { path = ".", version = "0.4.0-rc.4" } [workspace] members = ["async", "blocking"] [package] name = "ringbuf" -version = "0.4.0-rc.3" +version = "0.4.0-rc.4" edition.workspace = true authors.workspace = true description = "Lock-free SPSC FIFO ring buffer with direct access to inner data" diff --git a/src/rb/local.rs b/src/rb/local.rs index 1145d52..c2d383e 100644 --- a/src/rb/local.rs +++ b/src/rb/local.rs @@ -25,7 +25,7 @@ struct End { } impl End { - fn new(index: usize) -> Self { + const fn new(index: usize) -> Self { Self { index: Cell::new(index), held: Cell::new(false), @@ -49,8 +49,9 @@ impl LocalRb { /// /// The items in storage inside `read..write` range must be initialized, items outside this range must be uninitialized. /// `read` and `write` positions must be valid (see implementation details). - pub unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { - assert!(!storage.is_empty()); + /// + /// `storage` length must be non-zero. + pub const unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { Self { storage, read: End::new(read), diff --git a/src/rb/macros.rs b/src/rb/macros.rs index 26251d3..8b698b6 100644 --- a/src/rb/macros.rs +++ b/src/rb/macros.rs @@ -2,7 +2,12 @@ macro_rules! rb_impl_init { ($type:ident) => { impl Default for $type> { fn default() -> Self { - unsafe { Self::from_raw_parts(crate::utils::uninit_array().into(), usize::default(), usize::default()) } + Self::new() + } + } + impl $type> { + pub const fn new() -> Self { + unsafe { Self::from_raw_parts(crate::storage::Array::new(crate::utils::uninit_array()), 0, 0) } } } diff --git a/src/rb/shared.rs b/src/rb/shared.rs index c73cba6..36cad99 100644 --- a/src/rb/shared.rs +++ b/src/rb/shared.rs @@ -59,8 +59,9 @@ impl SharedRb { /// /// The items in storage inside `read..write` range must be initialized, items outside this range must be uninitialized. /// `read` and `write` positions must be valid (see implementation details). - pub unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { - assert!(!storage.is_empty()); + /// + /// `storage` length must be non-zero. + pub const unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { Self { storage, read_index: CachePadded::new(AtomicUsize::new(read)), diff --git a/src/storage.rs b/src/storage.rs index 891af01..430cb88 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -93,6 +93,11 @@ pub struct Owning { unsafe impl Sync for Owning where T: Sync {} impl From for Owning { fn from(value: T) -> Self { + Self::new(value) + } +} +impl Owning { + pub const fn new(value: T) -> Self { Self { data: UnsafeCell::new(value), } diff --git a/src/tests/new.rs b/src/tests/new.rs index 7c17f3f..4cf6dda 100644 --- a/src/tests/new.rs +++ b/src/tests/new.rs @@ -3,6 +3,9 @@ use crate::{storage::Array, traits::*}; #[cfg(feature = "alloc")] use alloc::vec::Vec; +#[allow(clippy::declare_interior_mutable_const)] +const _RB: Rb> = Rb::>::new(); + #[test] fn new_static() { let rb = Rb::>::default(); diff --git a/src/utils.rs b/src/utils.rs index e70e05b..14fb185 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,7 +6,7 @@ use core::{ }; // TODO: Remove on `maybe_uninit_uninit_array` stabilization. -pub fn uninit_array() -> [MaybeUninit; N] { +pub const fn uninit_array() -> [MaybeUninit; N] { unsafe { MaybeUninit::<[MaybeUninit; N]>::uninit().assume_init() } } @@ -39,21 +39,20 @@ pub fn move_uninit_slice(dst: &mut [MaybeUninit], src: &[MaybeUninit]) } pub fn array_to_uninit(value: [T; N]) -> [MaybeUninit; N] { - let value = mem::ManuallyDrop::new(value); - let ptr = &value as *const _ as *const [MaybeUninit; N]; - unsafe { ptr.read() } + let value = MaybeUninit::new(value); + let this = &value as *const _ as *const [MaybeUninit; N]; + unsafe { this.read() } } #[cfg(feature = "alloc")] -pub fn vec_to_uninit(value: Vec) -> Vec> { - let value = mem::ManuallyDrop::new(value); - let ptr = &value as *const _ as *const Vec>; - unsafe { ptr.read() } +pub fn vec_to_uninit(mut value: Vec) -> Vec> { + let (ptr, len, cap) = (value.as_mut_ptr() as *mut MaybeUninit, value.len(), value.capacity()); + mem::forget(value); + unsafe { Vec::from_raw_parts(ptr, len, cap) } } #[cfg(feature = "alloc")] pub fn boxed_slice_to_uninit(value: Box<[T]>) -> Box<[MaybeUninit]> { - let value = mem::ManuallyDrop::new(value); - let ptr = &value as *const _ as *const Box<[MaybeUninit]>; - unsafe { ptr.read() } + let ptr = Box::into_raw(value) as *mut [MaybeUninit]; + unsafe { Box::from_raw(ptr) } }