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
- High-Performance Loops: When you need to iterate over thousands of objects (physics, rendering) using linear memory prefetching.
- Structure of Arrays (SoA): When you want to keep parallel arrays (e.g.,
positions,velocities) synchronized with a single manager. - 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.
- Slot
Manager - A decoupled manager for handles and indices.