From e074043ef8566b06c12dbf73fb2d0b0bb805c983 Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sun, 11 Aug 2024 16:35:06 +0200 Subject: [PATCH 1/7] Add support for initialising the pool on creation. --- src/lib.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 66ad238..16dc5e2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ where [AtomicU32; K]: Sized, { used: AtomicBitset, - data: [UnsafeCell>; N], + pub data: [UnsafeCell>; N], } unsafe impl Send for PoolStorageImpl {} @@ -244,6 +244,21 @@ macro_rules! pool { } } }; + ($vis:vis $name:ident: [$ty:ty; $n:expr], $initial_value:expr) => { + $vis struct $name { _uninhabited: ::core::convert::Infallible } + impl $crate::Pool for $name { + type Item = $ty; + type Storage = $crate::PoolStorageImpl<$ty, {$n}, {($n+31)/32}>; + fn get() -> &'static Self::Storage { + static POOL: $crate::PoolStorageImpl<$ty, {$n}, {($n+31)/32}> = { + let mut pool_storage_impl = $crate::PoolStorageImpl::new(); + pool_storage_impl.data = unsafe { ::core::mem::transmute($initial_value) }; + pool_storage_impl + }; + &POOL + } + } + }; } #[cfg(test)] mod test { From c823b87e575b2fa8a5e8d2012317007254806ad8 Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sun, 11 Aug 2024 16:35:37 +0200 Subject: [PATCH 2/7] Allow allocating, a potentially uninitialised box. --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 16dc5e2..ba5cda4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,13 @@ impl Box

{ unsafe { p.as_ptr().write(item) }; Some(Self { ptr: p }) } + pub unsafe fn new_potentially_uninit() -> Option { + let p = match P::get().alloc() { + Some(p) => p, + None => return None, + }; + Some(Self { ptr: p }) + } pub fn into_raw(b: Self) -> NonNull { let res = b.ptr; From 54dc3e91d51e23b7ce8e16a0c13730edd8a98a3c Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sun, 11 Aug 2024 16:37:22 +0200 Subject: [PATCH 3/7] Added docs. --- src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ba5cda4..98d8583 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,7 +44,6 @@ where } } } - impl PoolStorage for PoolStorageImpl where [AtomicU32; K]: Sized, @@ -77,11 +76,13 @@ pub trait Pool: 'static { fn get() -> &'static Self::Storage; } +/// A statically allocated box. pub struct Box { ptr: NonNull, } impl Box

{ + /// Attempt to allocate a new item from the pool. pub fn new(item: P::Item) -> Option { let p = match P::get().alloc() { Some(p) => p, @@ -90,6 +91,9 @@ impl Box

{ unsafe { p.as_ptr().write(item) }; Some(Self { ptr: p }) } + /// Attempt to allocate a potentially unitialized item from the pool. + /// + /// This means, that data from a previous allocation may still be present or the memory is still uninitialized, so caution is advised. pub unsafe fn new_potentially_uninit() -> Option { let p = match P::get().alloc() { Some(p) => p, @@ -239,6 +243,9 @@ where } #[macro_export] +/// Create a new pool. +/// +/// This macro has to variants, one where the pool is uninitialized and another, where it is initialized to some initial value. macro_rules! pool { ($vis:vis $name:ident: [$ty:ty; $n:expr]) => { $vis struct $name { _uninhabited: ::core::convert::Infallible } From 8a15bd4b651b7a943ef2ddf47337875637bf8f9b Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sun, 11 Aug 2024 16:37:29 +0200 Subject: [PATCH 4/7] Adjusted examples. --- examples/initialised.rs | 23 +++++++++++++++++++++++ examples/simple.rs | 1 + 2 files changed, 24 insertions(+) create mode 100644 examples/initialised.rs diff --git a/examples/initialised.rs b/examples/initialised.rs new file mode 100644 index 0000000..94d6d26 --- /dev/null +++ b/examples/initialised.rs @@ -0,0 +1,23 @@ +use atomic_pool::{pool, Box}; +use std::mem; + +pool!(TestPool: [u32; 3], [0u32; 3]); + +fn main() { + let mut buffer = unsafe { Box::::new_potentially_uninit() }.unwrap(); + println!("Allocated new buffer, with contents: {:#x}", *buffer); + + *buffer = 0xf00dbabeu32; + + let _buffer_2 = unsafe { Box::::new_potentially_uninit() }.unwrap(); + let _buffer_3 = unsafe { Box::::new_potentially_uninit() }.unwrap(); + + mem::drop(buffer); + println!("Dropped buffer."); + + let reallocated_buffer = unsafe { Box::::new_potentially_uninit() }.unwrap(); + println!( + "Reallocated buffer, with contents: 0x{:#x}", + *reallocated_buffer + ); +} diff --git a/examples/simple.rs b/examples/simple.rs index 3e4a706..9f4666a 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,3 +1,4 @@ +#![allow(unused)] use std::mem; use atomic_pool::{pool, Box}; From 6030953496d637a02f6f50773dddda3f969ec98f Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sun, 11 Aug 2024 16:50:44 +0200 Subject: [PATCH 5/7] Renamed function and created safety comments. --- examples/initialised.rs | 8 ++++---- src/lib.rs | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/examples/initialised.rs b/examples/initialised.rs index 94d6d26..6d477cf 100644 --- a/examples/initialised.rs +++ b/examples/initialised.rs @@ -4,18 +4,18 @@ use std::mem; pool!(TestPool: [u32; 3], [0u32; 3]); fn main() { - let mut buffer = unsafe { Box::::new_potentially_uninit() }.unwrap(); + let mut buffer = unsafe { Box::::new_uninit() }.unwrap(); println!("Allocated new buffer, with contents: {:#x}", *buffer); *buffer = 0xf00dbabeu32; - let _buffer_2 = unsafe { Box::::new_potentially_uninit() }.unwrap(); - let _buffer_3 = unsafe { Box::::new_potentially_uninit() }.unwrap(); + let _buffer_2 = unsafe { Box::::new_uninit() }.unwrap(); + let _buffer_3 = unsafe { Box::::new_uninit() }.unwrap(); mem::drop(buffer); println!("Dropped buffer."); - let reallocated_buffer = unsafe { Box::::new_potentially_uninit() }.unwrap(); + let reallocated_buffer = unsafe { Box::::new_uninit() }.unwrap(); println!( "Reallocated buffer, with contents: 0x{:#x}", *reallocated_buffer diff --git a/src/lib.rs b/src/lib.rs index 98d8583..78ffb29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,9 +92,11 @@ impl Box

{ Some(Self { ptr: p }) } /// Attempt to allocate a potentially unitialized item from the pool. - /// - /// This means, that data from a previous allocation may still be present or the memory is still uninitialized, so caution is advised. - pub unsafe fn new_potentially_uninit() -> Option { + /// + /// # Safety + /// The area of memory, to which this box points, maybe uninitialized or contain data from a previous allocation. + /// You must ensure, that you handle this properly and initialize it yourself. + pub unsafe fn new_uninit() -> Option { let p = match P::get().alloc() { Some(p) => p, None => return None, @@ -102,12 +104,21 @@ impl Box

{ Some(Self { ptr: p }) } + /// Turn this box into a raw pointer. + /// + /// Once you turn a box into a raw pointer, it becomes your responsibility to free it properly again. + /// This can be done, by creating a box from that raw pointer again, using [Self::from_raw]. pub fn into_raw(b: Self) -> NonNull { let res = b.ptr; mem::forget(b); res } + /// Create a box from a raw pointer. + /// + /// # Safety + /// You must ensure, that the pointer points to valid memory, which was allocated from the pool in the generic parameter. + /// If you fail to do so, this will trigger a panic, once this box is dropped. pub unsafe fn from_raw(ptr: NonNull) -> Self { Self { ptr } } From 380e3fb72a616addcfa77bbd0e833b299f9ac9d3 Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sat, 17 Aug 2024 11:47:33 +0200 Subject: [PATCH 6/7] Removed pool initialization. --- examples/{initialised.rs => uninit.rs} | 6 +++--- src/lib.rs | 21 +++------------------ 2 files changed, 6 insertions(+), 21 deletions(-) rename examples/{initialised.rs => uninit.rs} (75%) diff --git a/examples/initialised.rs b/examples/uninit.rs similarity index 75% rename from examples/initialised.rs rename to examples/uninit.rs index 6d477cf..9075fd4 100644 --- a/examples/initialised.rs +++ b/examples/uninit.rs @@ -1,11 +1,11 @@ use atomic_pool::{pool, Box}; use std::mem; -pool!(TestPool: [u32; 3], [0u32; 3]); +pool!(TestPool: [u32; 3]); fn main() { let mut buffer = unsafe { Box::::new_uninit() }.unwrap(); - println!("Allocated new buffer, with contents: {:#x}", *buffer); + println!("Allocated new buffer."); *buffer = 0xf00dbabeu32; @@ -17,7 +17,7 @@ fn main() { let reallocated_buffer = unsafe { Box::::new_uninit() }.unwrap(); println!( - "Reallocated buffer, with contents: 0x{:#x}", + "Reallocated buffer, with contents: {:#x}", *reallocated_buffer ); } diff --git a/src/lib.rs b/src/lib.rs index 78ffb29..a2d2ffa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -105,8 +105,8 @@ impl Box

{ } /// Turn this box into a raw pointer. - /// - /// Once you turn a box into a raw pointer, it becomes your responsibility to free it properly again. + /// + /// Once you turn a box into a raw pointer, it becomes your responsibility to free it properly again. /// This can be done, by creating a box from that raw pointer again, using [Self::from_raw]. pub fn into_raw(b: Self) -> NonNull { let res = b.ptr; @@ -115,7 +115,7 @@ impl Box

{ } /// Create a box from a raw pointer. - /// + /// /// # Safety /// You must ensure, that the pointer points to valid memory, which was allocated from the pool in the generic parameter. /// If you fail to do so, this will trigger a panic, once this box is dropped. @@ -269,21 +269,6 @@ macro_rules! pool { } } }; - ($vis:vis $name:ident: [$ty:ty; $n:expr], $initial_value:expr) => { - $vis struct $name { _uninhabited: ::core::convert::Infallible } - impl $crate::Pool for $name { - type Item = $ty; - type Storage = $crate::PoolStorageImpl<$ty, {$n}, {($n+31)/32}>; - fn get() -> &'static Self::Storage { - static POOL: $crate::PoolStorageImpl<$ty, {$n}, {($n+31)/32}> = { - let mut pool_storage_impl = $crate::PoolStorageImpl::new(); - pool_storage_impl.data = unsafe { ::core::mem::transmute($initial_value) }; - pool_storage_impl - }; - &POOL - } - } - }; } #[cfg(test)] mod test { From 1d3443a6a49d4e7101dffaa2e00e1b7dc687571f Mon Sep 17 00:00:00 2001 From: Frostie314159 Date: Sat, 17 Aug 2024 11:50:15 +0200 Subject: [PATCH 7/7] Moved new_uninit behind a feature gate. --- Cargo.toml | 10 ++++------ examples/uninit.rs | 8 ++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a826f1f..7917696 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,15 +7,13 @@ repository = "https://github.com/embassy-rs/atomic-pool" edition = "2021" readme = "README.md" license = "MIT OR Apache-2.0" -categories = [ - "embedded", - "no-std", - "concurrency", - "memory-management", -] +categories = ["embedded", "no-std", "concurrency", "memory-management"] [dependencies] atomic-polyfill = "1.0" as-slice-01 = { package = "as-slice", version = "0.1.5" } as-slice-02 = { package = "as-slice", version = "0.2.1" } stable_deref_trait = { version = "1.2.0", default-features = false } + +[features] +alloc_uninit = [] diff --git a/examples/uninit.rs b/examples/uninit.rs index 9075fd4..6660200 100644 --- a/examples/uninit.rs +++ b/examples/uninit.rs @@ -1,9 +1,11 @@ -use atomic_pool::{pool, Box}; -use std::mem; +use atomic_pool::pool; pool!(TestPool: [u32; 3]); +#[cfg(feature = "alloc_uninit")] fn main() { + use atomic_pool::Box; + use std::mem; let mut buffer = unsafe { Box::::new_uninit() }.unwrap(); println!("Allocated new buffer."); @@ -21,3 +23,5 @@ fn main() { *reallocated_buffer ); } +#[cfg(not(feature = "alloc_uninit"))] +fn main() {}