ObjPool

Struct ObjPool 

Source
pub struct ObjPool<T> { /* private fields */ }
Expand description

An object pool.

ObjPool<T> holds an array of slots for storing objects. Every slot is always in one of two states: occupied or vacant.

Essentially, this is equivalent to Vec<Option<T>>.

§Insert and remove

When inserting a new object into object pool, a vacant slot is found and then the object is placed into the slot. If there are no vacant slots, the array is reallocated with bigger capacity. The cost of insertion is amortized O(1).

When removing an object, the slot containing it is marked as vacant and the object is returned. The cost of removal is O(1).

use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let a = obj_pool.insert(10);
assert_eq!(a.into_index(), 0);
let b = obj_pool.insert(20);
assert_eq!(b.into_index(), 1);

assert_ne!(a, b); // ids are not the same

assert_eq!(obj_pool.remove(a), Some(10));
assert_eq!(obj_pool.get(a), None); // there is no object with this `ObjId` anymore

assert_eq!(obj_pool.insert(30), a); // slot is reused, got the same `ObjId`

§Indexing

You can also access objects in an object pool by ObjId. However, accessing an object with invalid ObjId will result in panic.

use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let a = obj_pool.insert(10);
let b = obj_pool.insert(20);

assert_eq!(obj_pool[a], 10);
assert_eq!(obj_pool[b], 20);

obj_pool[a] += obj_pool[b];
assert_eq!(obj_pool[a], 30);

To access slots without fear of panicking, use get and get_mut, which return Options.

Implementations§

Source§

impl<T> ObjPool<T>

Source

pub const fn new() -> Self

Constructs a new, empty object pool.

The object pool will not allocate until objects are inserted into it.

§Examples
use obj_pool::ObjPool;

let mut obj_pool: ObjPool<i32> = ObjPool::new();
Source

pub const fn obj_id_to_index(obj_id: ObjId) -> u32

Get an index in the ObjPool for the given ObjId.

Source

pub fn index_to_obj_id(index: u32) -> ObjId

Make an ObjId from an index in this ObjPool.

Source

pub fn with_capacity(cap: usize) -> Self

Constructs a new, empty object pool with the specified capacity (number of slots).

The object pool will be able to hold exactly capacity objects without reallocating. If capacity is 0, the object pool will not allocate.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::with_capacity(10);

assert_eq!(obj_pool.len(), 0);
assert_eq!(obj_pool.capacity(), 10);

// These inserts are done without reallocating...
for i in 0..10 {
    obj_pool.insert(i);
}
assert_eq!(obj_pool.capacity(), 10);

// ... but this one will reallocate.
obj_pool.insert(11);
assert!(obj_pool.capacity() > 10);
Source

pub fn capacity(&self) -> usize

Returns the number of slots in the object pool.

§Examples
use obj_pool::ObjPool;

let obj_pool: ObjPool<i32> = ObjPool::with_capacity(10);
assert_eq!(obj_pool.capacity(), 10);
Source

pub fn len(&self) -> u32

Returns the number of occupied slots in the object pool.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
assert_eq!(obj_pool.len(), 0);

for i in 0..10 {
    obj_pool.insert(());
    assert_eq!(obj_pool.len(), i + 1);
}
Source

pub fn is_empty(&self) -> bool

Returns true if all slots are vacant.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
assert!(obj_pool.is_empty());

obj_pool.insert(1);
assert!(!obj_pool.is_empty());
Source

pub fn next_vacant(&mut self) -> ObjId

Returns the ObjId of the next inserted object if no other mutating calls take place in between.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();

let a = obj_pool.next_vacant();
let b = obj_pool.insert(1);
assert_eq!(a, b);
let c = obj_pool.next_vacant();
let d = obj_pool.insert(2);
assert_eq!(c, d);
Source

pub fn insert(&mut self, object: T) -> ObjId

Inserts an object into the object pool and returns the ObjId of this object. The object pool will reallocate if it’s full.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();

let a = obj_pool.insert(1);
let b = obj_pool.insert(2);
assert!(a != b);
Source

pub fn remove(&mut self, obj_id: ObjId) -> Option<T>

Removes the object stored by ObjId from the object pool and returns it.

None is returned in case the there is no object with such an ObjId.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let a = obj_pool.insert("hello");

assert_eq!(obj_pool.len(), 1);
assert_eq!(obj_pool.remove(a), Some("hello"));

assert_eq!(obj_pool.len(), 0);
assert_eq!(obj_pool.remove(a), None);
Source

pub fn clear(&mut self)

Clears the object pool, removing and dropping all objects it holds. Keeps the allocated memory for reuse.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
for i in 0..10 {
    obj_pool.insert(i);
}

assert_eq!(obj_pool.len(), 10);
obj_pool.clear();
assert_eq!(obj_pool.len(), 0);
Source

pub fn get(&self, obj_id: ObjId) -> Option<&T>

Returns a reference to the object by its ObjId.

If object is not found with given obj_id, None is returned.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let obj_id = obj_pool.insert("hello");

assert_eq!(obj_pool.get(obj_id), Some(&"hello"));
obj_pool.remove(obj_id);
assert_eq!(obj_pool.get(obj_id), None);
Source

pub fn get_mut(&mut self, obj_id: ObjId) -> Option<&mut T>

Returns a mutable reference to the object by its ObjId.

If object can’t be found, None is returned.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let obj_id = obj_pool.insert(7);

assert_eq!(obj_pool.get_mut(obj_id), Some(&mut 7));
*obj_pool.get_mut(obj_id).unwrap() *= 10;
assert_eq!(obj_pool.get_mut(obj_id), Some(&mut 70));
Source

pub unsafe fn get_unchecked(&self, obj_id: ObjId) -> &T

Returns a reference to the object by its ObjId.

§Safety

Behavior is undefined if object can’t be found.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let obj_id = obj_pool.insert("hello");

unsafe { assert_eq!(&*obj_pool.get_unchecked(obj_id), &"hello") }
Source

pub unsafe fn get_unchecked_mut(&mut self, obj_id: ObjId) -> &mut T

Returns a mutable reference to the object by its ObjId.

§Safety

Behavior is undefined if object can’t be found.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let obj_id = obj_pool.insert("hello");

unsafe { assert_eq!(&*obj_pool.get_unchecked_mut(obj_id), &"hello") }
Source

pub fn swap(&mut self, a: ObjId, b: ObjId)

Swaps two objects in the object pool.

The two ObjIds are a and b.

§Panics

Panics if any of the ObjIds is invalid.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
let a = obj_pool.insert(7);
let b = obj_pool.insert(8);

obj_pool.swap(a, b);
assert_eq!(obj_pool.get(a), Some(&8));
assert_eq!(obj_pool.get(b), Some(&7));
Source

pub fn reserve(&mut self, additional: u32)

Reserves capacity for at least additional more objects to be inserted. The object pool may reserve more space to avoid frequent reallocations.

§Panics

Panics if the new capacity overflows u32.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
obj_pool.insert("hello");

obj_pool.reserve(10);
assert!(obj_pool.capacity() >= 11);
Source

pub fn reserve_exact(&mut self, additional: u32)

Reserves the minimum capacity for exactly additional more objects to be inserted.

Note that the allocator may give the object pool more space than it requests.

§Panics

Panics if the new capacity overflows u32.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
obj_pool.insert("hello");

obj_pool.reserve_exact(10);
assert!(obj_pool.capacity() >= 11);
Source

pub fn iter(&self) -> Iter<'_, T>

Returns an iterator over occupied slots.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
obj_pool.insert(1);
obj_pool.insert(2);
obj_pool.insert(4);

let mut iterator = obj_pool.iter();
assert_eq!(iterator.next(), Some((ObjPool::<usize>::index_to_obj_id(0), &1)));
assert_eq!(iterator.next(), Some((ObjPool::<usize>::index_to_obj_id(1), &2)));
assert_eq!(iterator.next(), Some((ObjPool::<usize>::index_to_obj_id(2), &4)));
Source

pub fn iter_mut(&mut self) -> IterMut<'_, T>

Returns an iterator that returns mutable references to objects.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::new();
obj_pool.insert("zero".to_string());
obj_pool.insert("one".to_string());
obj_pool.insert("two".to_string());

for (obj_id, object) in obj_pool.iter_mut() {
    *object = obj_id.into_index().to_string() + " " + object;
}

let mut iterator = obj_pool.iter();
assert_eq!(iterator.next(), Some((ObjPool::<String>::index_to_obj_id(0), &"0 zero".to_string())));
assert_eq!(iterator.next(), Some((ObjPool::<String>::index_to_obj_id(1), &"1 one".to_string())));
assert_eq!(iterator.next(), Some((ObjPool::<String>::index_to_obj_id(2), &"2 two".to_string())));
Source

pub fn shrink_to_fit(&mut self)

Shrinks the capacity of the object pool as much as possible.

It will drop down as close as possible to the length but the allocator may still inform the object pool that there is space for a few more elements.

§Examples
use obj_pool::ObjPool;

let mut obj_pool = ObjPool::with_capacity(10);
obj_pool.insert("first".to_string());
obj_pool.insert("second".to_string());
obj_pool.insert("third".to_string());
assert_eq!(obj_pool.capacity(), 10);
obj_pool.shrink_to_fit();
assert!(obj_pool.capacity() >= 3);

Trait Implementations§

Source§

impl<T> AsMut<ObjPool<T>> for ObjPool<T>

Source§

fn as_mut(&mut self) -> &mut ObjPool<T>

Converts this type into a mutable reference of the (usually inferred) input type.
Source§

impl<T> AsRef<ObjPool<T>> for ObjPool<T>

Source§

fn as_ref(&self) -> &ObjPool<T>

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<T: Clone> Clone for ObjPool<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Debug for ObjPool<T>

Source§

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

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

impl<T> Default for ObjPool<T>

Source§

fn default() -> Self

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

impl<T> FromIterator<T> for ObjPool<T>

Source§

fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> ObjPool<T>

Creates a value from an iterator. Read more
Source§

impl<T> Index<ObjId> for ObjPool<T>

Source§

type Output = T

The returned type after indexing.
Source§

fn index(&self, obj_id: ObjId) -> &T

Performs the indexing (container[index]) operation. Read more
Source§

impl<T> IndexMut<ObjId> for ObjPool<T>

Source§

fn index_mut(&mut self, obj_id: ObjId) -> &mut T

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl<'a, T> IntoIterator for &'a ObjPool<T>

Source§

type Item = (ObjId, &'a T)

The type of the elements being iterated over.
Source§

type IntoIter = Iter<'a, T>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<'a, T> IntoIterator for &'a mut ObjPool<T>

Source§

type Item = (ObjId, &'a mut T)

The type of the elements being iterated over.
Source§

type IntoIter = IterMut<'a, T>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<T> IntoIterator for ObjPool<T>

Source§

type Item = (ObjId, T)

The type of the elements being iterated over.
Source§

type IntoIter = IntoIter<T>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more

Auto Trait Implementations§

§

impl<T> Freeze for ObjPool<T>

§

impl<T> RefUnwindSafe for ObjPool<T>
where T: RefUnwindSafe,

§

impl<T> Send for ObjPool<T>
where T: Send,

§

impl<T> Sync for ObjPool<T>
where T: Sync,

§

impl<T> Unpin for ObjPool<T>
where T: Unpin,

§

impl<T> UnwindSafe for ObjPool<T>
where T: UnwindSafe,

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.