Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A slot map is a high-performance associative container with persistent unique 32/64 bit keys to access stored values.

License

NotificationsYou must be signed in to change notification settings

SergeyMakeev/SlotMap

Repository files navigation

Licensecicodecov

A Slot Map is a high-performance associative container with persistent unique keys to access stored values. It's designed for performance-critical applications where stable references, O(1) operations, and memory efficiency are essential.

Table of Contents

What is a Slot Map?

A Slot Map solves the problem of storing collections of objects that need stable, safe references but have no clear ownership hierarchy. Unlikestd::unordered_map where you provide keys, a slot mapgenerates unique keys when you insert values.

Key differences fromstd::unordered_map:

  • Slot map generates keys for you (no key collisions)
  • Guaranteed O(1) insertion, removal, and access
  • Memory-stable pointers (values never move in memory)
  • Automatic key invalidation when items are removed
  • Efficient memory layout with page-based allocation

Perfect for:

  • Game entities and component systems
  • Resource management (textures, sounds, etc.)
  • Object pools and handle-based systems
  • Any scenario requiring safe, stable references

Key Features

  • O(1) Performance: Insertion, removal, and access are all O(1) in best, worst, and average case
  • Memory Stability: Pointers to values remain valid until explicitly removed
  • Safe References: Keys automatically become invalid when items are removed
  • Memory Efficient: Page-based allocation prevents memory fragmentation
  • Type Safety: Keys are typed to prevent mixing between different slot maps
  • Iteration Support: Both value-only and key-value iteration
  • Custom Allocators: Support for custom memory allocators
  • Header Only: Single header file, easy to integrate

Quick Start

#include"slot_map.h"// Create a slot map for stringsdod::slot_map<std::string> strings;// Insert values and get unique keysauto red_key = strings.emplace("Red");auto green_key = strings.emplace("Green");auto blue_key = strings.emplace("Blue");// Access values using keysconst std::string* red_value = strings.get(red_key);if (red_value) {printf("Color: %s\n", red_value->c_str());// Output: Color: Red}// Remove a valuestrings.erase(green_key);// Check if keys are still validprintf("Green exists: %d\n", strings.has_key(green_key));// Output: 0printf("Blue exists: %d\n", strings.has_key(blue_key));// Output: 1// Iterate over all valuesfor (constauto& color : strings) {printf("Color: %s\n", color.c_str());}// Iterate over key-value pairsfor (constauto& [key, color] : strings.items()) {printf("Key: %" PRIslotkey", Color: %s\n",uint64_t(key), color.get().c_str());}

Building

Requirements

  • C++17 or later
  • CMake 3.10 or later (for building tests)

Header-Only Integration

Simply include the header file in your project:

#include"slot_map/slot_map.h"

Building Tests

git clone https://github.com/SergeyMakeev/SlotMap.gitcd SlotMapmkdir build&&cd buildcmake ..cmake --build.# Run tests./SlotMapTest01./SlotMapTest02./SlotMapTest03./SlotMapTest04

Custom Memory Allocator

Define custom allocator macros before including the header:

#defineSLOT_MAP_ALLOC(sizeInBytes, alignment) your_aligned_alloc(alignment, sizeInBytes)#defineSLOT_MAP_FREE(ptr) your_free(ptr)#include"slot_map.h"

API Reference

Core Operations

emplace(Args&&... args) -> key

Constructs element in-place and returns a unique key.

auto key = slot_map.emplace("Hello","World");// Construct string from args

get(key k) -> T* /get(key k) const -> const T*

Returns pointer to value ornullptr if key is invalid.

const std::string* value = slot_map.get(key);

has_key(key k) const -> bool

Returnstrue if the key exists and is valid.

if (slot_map.has_key(key)) {/* key is valid*/ }

erase(key k)

Removes element if key exists. Key becomes invalid.

slot_map.erase(key);

pop(key k) -> std::optional<T>

Removes and returns the value if key exists.

auto value = slot_map.pop(key);// Returns optional<T>

Container Operations

size() const -> size_type

Returns number of elements.

empty() const -> bool

Returnstrue if container is empty.

clear()

Removes all elements but keeps allocated memory. Invalidates all keys.

reset()

Removes all elements and releases memory.Warning: Only call when no keys are in use.

swap(slot_map& other)

Exchanges contents with another slot map.

Iteration

Value iteration

for (constauto& value : slot_map) {// Process value}

Key-value iteration

for (constauto& [key, value] : slot_map.items()) {// Process key and value}

Debug and Statistics

debug_stats() const -> Stats

Returns internal statistics (O(n) complexity).

auto stats = slot_map.debug_stats();printf("Active items: %u\n", stats.numAliveItems);

Key Types

64-bit Keys (Default)

dod::slot_map<T>// Uses 64-bit keysdod::slot_map64<T>// Explicit 64-bit keys
ComponentBitsRange
Tag120..4,095
Version200..1,048,575
Index320..4,294,967,295

32-bit Keys

dod::slot_map32<T>// Uses 32-bit keys
ComponentBitsRange
Tag20..3
Version100..1,023
Index200..1,048,575

Key Operations

auto key = slot_map.emplace(value);// Type-safe: this won't compile// slot_map<int>::key int_key = int_map.emplace(42);// string_map.get(int_key);  // Compiler error!// Convert to/from raw numeric typeuint64_t raw_key = key;// Implicit conversionslot_map<T>::key restored_key{raw_key};// Explicit construction

Advanced Features

Tags

Keys can store small amounts of user data:

auto key = slot_map.emplace("Value");key.set_tag(42);// Store application dataauto tag = key.get_tag();// Retrieve: tag == 42// Tag limits:// 64-bit keys: 0..4,095 (12 bits)// 32-bit keys: 0..3 (2 bits)

Custom Page Size

Adjust memory allocation granularity:

// Default page size is 4096 elementsdod::slot_map<T, dod::slot_map_key64<T>,8192> large_pages;dod::slot_map<T, dod::slot_map_key64<T>,1024> small_pages;

Custom Free Indices Threshold

Control when slot indices are reused:

// Default threshold is 64dod::slot_map<T, dod::slot_map_key64<T>,4096,128> conservative_reuse;

Performance

Time Complexity

  • Insertion: O(1) amortized
  • Removal: O(1)
  • Access: O(1)
  • Iteration: O(n) where n is number of alive elements

Memory Characteristics

  • Page-based allocation: 4096 elements per page by default
  • Pointer stability: Values never move once allocated
  • Memory efficiency: Pages are released when all slots become inactive
  • Cache-friendly: Sequential iteration over alive elements only

Implementation Details

Version Overflow Protection

When a slot's version counter reaches maximum value:

  1. The slot is marked as inactive
  2. No new keys will be generated for this slot
  3. Guarantees no key collisions even with version wrap-around

Free Index Management

  • Recently freed slots aren't immediately reused
  • Minimum threshold (default 64) prevents rapid version increments
  • Balances memory usage with collision avoidance

Page Management

  • Elements are allocated in pages (default 4096 elements)
  • Pages are released when all slots in a page become inactive
  • Provides memory stability and prevents fragmentation

Thread Safety

Slot maps are NOT thread-safe. External synchronization is required for:

  • Concurrent access from multiple threads
  • Reader-writer scenarios

For thread-safe usage:

std::shared_mutex mutex;dod::slot_map<T> slot_map;// Reader{    std::shared_locklock(mutex);auto value = slot_map.get(key);}// Writer{    std::unique_locklock(mutex);auto key = slot_map.emplace(value);}

Examples

Entity Component System

structTransform {float x, y, z; };structHealth {int hp, max_hp; };dod::slot_map<Transform> transforms;dod::slot_map<Health> healths;// Create entityauto entity_id = generate_entity_id();auto transform_key = transforms.emplace(Transform{0,0,0});auto health_key = healths.emplace(Health{100,100});// Store keys in entityregister_component(entity_id, transform_key);register_component(entity_id, health_key);

Resource Management

dod::slot_map<Texture> textures;dod::slot_map<Sound> sounds;classResourceManager {using TextureHandle = dod::slot_map<Texture>::key;using SoundHandle = dod::slot_map<Sound>::key;        TextureHandleload_texture(const std::string& path) {return textures.emplace(load_texture_from_file(path));    }const Texture*get_texture(TextureHandle handle) {return textures.get(handle);    }};

Object Pool with Versioning

classBulletPool {structBullet {float x, y, dx, dy;bool active; };    dod::slot_map<Bullet> bullets;public:using BulletHandle = dod::slot_map<Bullet>::key;        BulletHandlespawn(float x,float y,float dx,float dy) {return bullets.emplace(Bullet{x, y, dx, dy,true});    }voidupdate() {for (auto& bullet : bullets) {if (bullet.active) {                bullet.x += bullet.dx;                bullet.y += bullet.dy;            }        }    }voiddestroy(BulletHandle handle) {        bullets.erase(handle);// Handle becomes invalid automatically    }};

References

About

A slot map is a high-performance associative container with persistent unique 32/64 bit keys to access stored values.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp