LocklessSlotmap

Struct LocklessSlotmap 

Source
pub struct LocklessSlotmap<T, R>
where T: Sized + Send + Sync, R: RawRwLock,
{ /* private fields */ }
Expand description

LocklessSlotmap is a lockless implementation of a slotmap.

A slotmap is a data structure that allows for stable references to elements while providing fast insertion (in O(1) time) and removal (in O(1) time).

This implementation is (mostly) lockless, meaning that it can be used in a high performance environment where locks are not desired. The only place where locks are used is when the slotmap becomes saturated and a new block needs to be allocated. Because of the ever-growing exponential size of the blocks, this should be a rare occurrence.

§Limitations

Each slot in the slotmap can only be reused so many times. 16-bit generation numbers are kept as guard against ABA problems, this means that each slot can only be reused 65536 times (after which the slot is considered “dead” and will not be reused which can lead to slowly increasing memory usage). Therefore for very long running applications with high insertion and removal rates, this implementation may not be suitable.

§Implementation

Internally, the slotmap is divided into blocks, each block containing a fixed number of elements. When the slotmap is saturated, a new block is allocated without invalidating all the already existing blocks. This allows for fast insertion and removal of elements.

Blocks grow exponentially in size, starting at 64 elements (default) and growing up to a maximum of MAX_ELEMENTS_PER_BLOCK elements.

§Note

In the current implementation, the insertion of new elements takes the place of the most recently removed element. At high loads this behavior can lead to excessive memory fragmentation. This behavior may be changed in the future.

Implementations§

Source§

impl<T, R> LocklessSlotmap<T, R>
where T: Sized + Send + Sync, R: RawRwLock,

Source

pub fn new() -> Self

Creates a new slotmap with the default capacity of 64 elements.

§Returns

A new slotmap with the default capacity of 64 elements.

§Panics

Panics if the allocation of the first block fails.

Source

pub fn with_capacity(capacity: usize) -> Self

Creates a new slotmap with the specified capacity.

§Arguments
  • capacity - The capacity (number of elements) of the slotmap. This capacity is limited to MAX_ELEMENTS_PER_BLOCK elements. However, this limit should allow for a slotmap with a capacity of up to 2^32 elements.
§Returns

A new slotmap with the specified capacity.

§Panics

Panics if the capacity is greater than MAX_ELEMENTS_PER_BLOCK.

Source

pub fn insert(&self, value: T) -> SlotmapTicket

Inserts a new element into the slotmap.

Atomically inserts a new element into the slotmap. The element is stored in the slotmap and a ticket is returned that can be used to access the element.

§Arguments
  • value - The value to insert into the slotmap.
§Returns

A ticket that can be used to access the element in the slotmap. The value of the ticket can then be accessed using the LocklessSlotmap::get method.

Source

pub fn get(&self, ticket: SlotmapTicket) -> Option<SlotmapEntry<'_, T>>

Get an element from the slotmap at the specified ticket.

Retrieves the element stored in the slotmap at the specified ticket. The ticket is invalidated after the element is removed from the slotmap. For more information you can refer to the SlotmapEntry structure.

§Arguments
  • ticket - The ticket of the element in the slotmap. Tickets are invalidated after the element is removed from the slotmap. See SlotmapTicket for more details.
§Returns

An Option<T> containing a SlotmapEntry to the element stored in the slotmap at the specified ticket. If the ticket is invalid or the element has been removed

Source

pub fn erase(&self, ticket: SlotmapTicket) -> Option<T>

Erase an element from the slotmap at the specified ticket.

Removes the element stored in the slotmap at the specified ticket. The ticket is invalidated after the element is removed from the slotmap. For more information you can refer to the SlotmapEntry structure.

§Deadlocks

This method will wait for all SlotmapEntry corresponding to the ticket to be dropped before removing the element from the slotmap. Special care should be taken to ensure that the thread calling this method is not holding a SlotmapEntry corresponding to the ticket or a deadlock will occur.

§Arguments
  • ticket - The ticket of the element in the slotmap. Tickets are invalidated
§Returns

An Option<T> containing the element stored in the slotmap at the specified ticket or Option::None if the ticket is invalid or the element has already been removed.

Source

pub fn capacity(&self) -> usize

Get the maximum number of elements that can be stored in the slotmap.

§Returns

The maximum number of elements that can be stored in the slotmap.

Source

pub fn len(&self) -> usize

Get the number of elements stored in the slotmap.

Notice that in a multithreaded environment, the number of elements stored in the slotmap can change between the time this method is called and the time the result is used, therefore this method should be used as an approximation.

§Returns

The number of elements stored in the slotmap.

Source

pub fn generation_limit_reached(&self) -> usize

Number of times the generation limit has been reached.

As discussed in the limitations of the LocklessSlotmap structure, each slot can only be reused so many times (2^16 times). When the generation limit is reached, the slot is considered “dead” and will not be reused. This method returns the number of times dead slots have been encountered.

Notice that in a multithreaded environment, the number of times the generation limit has been reached can change between the time this method is called and the time the result is used, therefore this method should be used as an approximation.

§Returns

The number of times the generation limit has been reached.

Trait Implementations§

Source§

impl<T, R> Drop for LocklessSlotmap<T, R>
where T: Sized + Send + Sync, R: RawRwLock,

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T, R> Send for LocklessSlotmap<T, R>
where T: Sized + Send + Sync, R: RawRwLock,

Source§

impl<T, R> Sync for LocklessSlotmap<T, R>
where T: Sized + Send + Sync, R: RawRwLock,

Auto Trait Implementations§

§

impl<T, R> !Freeze for LocklessSlotmap<T, R>

§

impl<T, R> !RefUnwindSafe for LocklessSlotmap<T, R>

§

impl<T, R> Unpin for LocklessSlotmap<T, R>
where R: Unpin,

§

impl<T, R> UnwindSafe for LocklessSlotmap<T, R>
where R: UnwindSafe, 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> 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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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.