Skip to main content

Crate slotmap_microlib

Crate slotmap_microlib 

Source
Expand description

§SlotManager

A high-performance, decoupled slot manager designed for Data-Oriented Design (DOD). It provides stable 64-bit handles to data stored in packed, contiguous arrays.

§Quick Example

use slotmap_microlib::{SlotManager, Handle};

let mut manager = SlotManager::new(10);
let mut data = Vec::new();

// the manager provides the index for adding data
let h1 = manager.add(|idx| data.push("Entity A"));

// resolve handle to current index
if let Some(idx) = manager.get(h1) {
    assert_eq!(data[idx], "Entity A");
}

// synchronize your array via swap-and-pop when removing
manager.remove(h1, |last_idx, to_rem_idx| {
    data.swap(to_rem_idx, last_idx);
    data.pop();
});

§What is a Slot Map?

A Slot Map is a data structure that provides the benefits of both a Vec and a HashMap. Like a Vec, it stores data contiguously in memory for maximum cache efficiency. Like a HashMap, it provides stable handles (keys) that remain valid even when the underlying data is moved or deleted.

The SlotManager implements the remapping logic (4-array parallel architecture) without taking ownership of your data. It acts as a management layer that tells you where to store your data and how to update your indices during removals.

§Comparison with Other Maps

The SlotManager provides $O(1)$ access via stable handles, combining the performance of a Vec with the stability of a HashMap. Like a Vec, it stores data contiguously for maximum iteration speed and avoids the overhead of a hash function. However, while a Vec is unstable because removals shift elements and invalidate indices, the SlotManager maintains stable handles throughout the lifecycle of the data, providing the same reliability as a HashMap without the cost of non-contiguous memory access.

§When to use this library

  1. High-Performance Loops: When you need to iterate over thousands of objects (physics, rendering) using linear memory prefetching.
  2. Structure of Arrays (SoA): When you want to keep parallel arrays (e.g., positions, velocities) synchronized with a single manager.
  3. Stable References: When external systems (like a scripting engine or UI) need to hold pointers to entities that are frequently added and removed.

§Wrapper Pattern

The SlotManager is meant to be used as part of a larger data structure, to internally manage the slots for its objects.

pub struct ParticleSystem {
    pos_x: Vec<f32>,
    pos_y: Vec<f32>,
    manager: SlotManager,
}

impl ParticleSystem {
    pub fn spawn(&mut self, x: f32, y: f32) -> Handle {
        self.manager.add(|idx| {
            if idx >= self.pos_x.len() {
                self.pos_x.push(x);
                self.pos_y.push(y);
            } else {
                self.pos_x[idx] = x;
                self.pos_y[idx] = y;
            }
        })
    }

    pub fn kill(&mut self, handle: Handle) {
        self.manager.remove(handle, |last, to_rem| {
            self.pos_x.swap(to_rem, last);
            self.pos_y.swap(to_rem, last);
            self.pos_x.pop();
            self.pos_y.pop();
        });
    }
}

Structs§

Handle
A bit-packed 64-bit handle containing a 32-bit generation and 32-bit slot ID.
SlotManager
A decoupled manager for handles and indices.