Pool

Struct Pool 

Source
pub struct Pool<T: Sized> { /* private fields */ }
Expand description

A single threaded arena

It produces only PoolBox and ArenaRc which cannot be sent to other threads.

Implementations§

Source§

impl<T: Sized> Pool<T>

Source

pub fn new() -> Pool<T>

Constructs a new Pool capable of holding exactly 63 elements

The Pool will reallocate itself if there is not enough space when allocating (with alloc* functions)

§Example
let arena = Pool::new();
Source

pub fn with_capacity(cap: usize) -> Pool<T>

Constructs a new Pool capable of holding at least cap elements

Because the arena allocate by page of 63 elements, it might be able to hold more elements than cap.

The Pool will reallocate itself if there is not enough space when allocating (with alloc* functions)

§Example
let arena = Pool::with_capacity(2048);
Source

pub fn alloc(&self, value: T) -> PoolBox<T>

Writes a value in the arena, and returns an PoolBox pointing to that value.

§Example
let arena = Pool::new();
let my_num: PoolBox<u8> = arena.alloc(0xFF);

assert_eq!(*my_num, 255);
Source

pub fn alloc_with<F>(&self, initializer: F) -> PoolBox<T>
where F: Fn(&mut MaybeUninit<T>) -> &T,

Finds an empty space in the arena and calls the function initializer with its argument pointing to that space. It returns an PoolBox pointing to the newly initialized value.

The difference with alloc is that it has the benefit of avoiding intermediate copies of the value.

§Safety

It is the caller responsability to initialize properly the value.
initializer must return &T, this is a way to ensure that its parameter &mut MaybeUninit<T> has been “consumed”.

If initializer returns a different reference than its parameter, the function will panic.

When the PoolBox is dropped, the value is also dropped. If the value is not initialized correctly, it will drop an unitialized value, which is undefined behavior.

§Example
struct MyData {
    a: usize
}

fn initialize_data<'a>(uninit: &'a mut MaybeUninit<MyData>, source: &MyData) -> &'a MyData {
    unsafe {
        let ptr = uninit.as_mut_ptr();
        ptr::copy(source, ptr, 1);
        &*ptr
    }
}

let arena = Pool::<MyData>::new();
let source = MyData { a: 101 };

let data = arena.alloc_with(|uninit| {
    initialize_data(uninit, &source)
});
assert!(data.a == 101);
Source

pub fn alloc_rc(&self, value: T) -> ArenaRc<T>

Writes a value in the arena, and returns an ArenaRc pointing to that value.

§Example
let arena = Pool::new();
let my_num: ArenaRc<u8> = arena.alloc_rc(0xFF);

assert_eq!(*my_num, 255);
Source

pub fn alloc_rc_with<F>(&self, initializer: F) -> ArenaRc<T>
where F: Fn(&mut MaybeUninit<T>) -> &T,

Finds an empty space in the arena and calls the function initializer with its argument pointing to that space. It returns an ArenaRc pointing to the newly initialized value.

The difference with alloc_rc is that it has the benefit of avoiding intermediate copies of the value.

§Safety

It is the caller responsability to initialize properly the value.
initializer must return &T, this is a way to ensure that its parameter &mut MaybeUninit<T> has been “consumed”.

If initializer returns a different reference than its parameter, the function will panic.

When all ArenaRc pointing that value are dropped, the value is also dropped. If the value is not initialized correctly, it will drop an unitialized value, which is undefined behavior.

§Example
struct MyData {
    a: usize
}

fn initialize_data<'a>(uninit: &'a mut MaybeUninit<MyData>, source: &MyData) -> &'a MyData {
    unsafe {
        let ptr = uninit.as_mut_ptr();
        ptr::copy(source, ptr, 1);
        &*ptr
    }
}

let arena = Pool::<MyData>::new();
let source = MyData { a: 101 };

let data = arena.alloc_rc_with(|uninit| {
    initialize_data(uninit, &source)
});
assert!(data.a == 101);
Source

pub fn stats(&self) -> (usize, usize)

Returns a tuple of non-free and free spaces in the arena

This is a slow function and it should not be called in a hot path.

§Example
let arena = Pool::new();
let item = arena.alloc(1);
let (used, free) = arena.stats();
assert!(used == 1 && free == 62);
Source

pub fn shrink_to_fit(&mut self)

Shrinks the capacity of the arena as much as possible.

It will drop all pages that are unused (no ArenaRc or PoolBox points to it).
If there is still one or more references to a page, the page won’t be dropped.

This is a slow function and it should not be called in a hot path.

The dedicated memory will be deallocated during this call.

§Example
let mut arena = Pool::with_capacity(2048);
let mut values = Vec::new();

assert_eq!(arena.stats(), (0, 2079));

for _ in 0..80 {
    values.push(arena.alloc(0xFF));
}

arena.shrink_to_fit();

let (used, free) = arena.stats();
assert!(used == 80, free == 46);

Trait Implementations§

Source§

impl<T> Debug for Pool<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Default for Pool<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<T> Drop for Pool<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for Pool<T>

§

impl<T> !RefUnwindSafe for Pool<T>

§

impl<T> !Send for Pool<T>

§

impl<T> !Sync for Pool<T>

§

impl<T> Unpin for Pool<T>

§

impl<T> !UnwindSafe for Pool<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.