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>
impl<T: Sized> Pool<T>
Sourcepub fn new() -> Pool<T>
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();Sourcepub fn with_capacity(cap: usize) -> Pool<T>
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);Sourcepub fn alloc_with<F>(&self, initializer: F) -> PoolBox<T>
pub fn alloc_with<F>(&self, initializer: F) -> PoolBox<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);Sourcepub fn alloc_rc_with<F>(&self, initializer: F) -> ArenaRc<T>
pub fn alloc_rc_with<F>(&self, initializer: F) -> ArenaRc<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);Sourcepub fn stats(&self) -> (usize, usize)
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);Sourcepub fn shrink_to_fit(&mut self)
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);