Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for initialising the pool to some value and allow allocating uninitialized boxes. #7

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
1 change: 1 addition & 0 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(unused)]
use std::mem;

use atomic_pool::{pool, Box};
Expand Down
27 changes: 27 additions & 0 deletions examples/uninit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
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::<TestPool>::new_uninit() }.unwrap();
println!("Allocated new buffer.");

*buffer = 0xf00dbabeu32;

let _buffer_2 = unsafe { Box::<TestPool>::new_uninit() }.unwrap();
let _buffer_3 = unsafe { Box::<TestPool>::new_uninit() }.unwrap();

mem::drop(buffer);
println!("Dropped buffer.");

let reallocated_buffer = unsafe { Box::<TestPool>::new_uninit() }.unwrap();
println!(
"Reallocated buffer, with contents: {:#x}",
*reallocated_buffer
);
}
#[cfg(not(feature = "alloc_uninit"))]
fn main() {}
29 changes: 27 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ where
[AtomicU32; K]: Sized,
{
used: AtomicBitset<N, K>,
data: [UnsafeCell<MaybeUninit<T>>; N],
pub data: [UnsafeCell<MaybeUninit<T>>; N],
}

unsafe impl<T, const N: usize, const K: usize> Send for PoolStorageImpl<T, N, K> {}
Expand All @@ -44,7 +44,6 @@ where
}
}
}

impl<T, const N: usize, const K: usize> PoolStorage<T> for PoolStorageImpl<T, N, K>
where
[AtomicU32; K]: Sized,
Expand Down Expand Up @@ -77,11 +76,13 @@ pub trait Pool: 'static {
fn get() -> &'static Self::Storage;
}

/// A statically allocated box.
pub struct Box<P: Pool> {
ptr: NonNull<P::Item>,
}

impl<P: Pool> Box<P> {
/// Attempt to allocate a new item from the pool.
pub fn new(item: P::Item) -> Option<Self> {
let p = match P::get().alloc() {
Some(p) => p,
Expand All @@ -90,13 +91,34 @@ impl<P: Pool> Box<P> {
unsafe { p.as_ptr().write(item) };
Some(Self { ptr: p })
}
/// Attempt to allocate a potentially unitialized item from the pool.
///
/// # 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<Self> {
let p = match P::get().alloc() {
Some(p) => p,
None => return None,
};
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<P::Item> {
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<P::Item>) -> Self {
Self { ptr }
}
Expand Down Expand Up @@ -232,6 +254,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 }
Expand Down
Loading