Added KeyedSlotMap
This commit is contained in:
parent
e5cf308609
commit
5c8e8434ec
4 changed files with 151 additions and 81 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
**Includes**
|
**Includes**
|
||||||
- ANSI
|
- ANSI
|
||||||
- SlotMap
|
- SlotMap | KeyedSlotMap
|
||||||
- Custom Log
|
- Custom Log
|
||||||
- TypeID
|
- TypeID
|
||||||
|
|
||||||
|
|
@ -14,10 +14,10 @@ log.trace("...", .{});
|
||||||
log.fatal("...", .{});
|
log.fatal("...", .{});
|
||||||
```
|
```
|
||||||
|
|
||||||
**SlotMap**
|
**KeyedSlotMap**
|
||||||
```zig
|
```zig
|
||||||
// --- SHADER MAP ---
|
// --- SHADER MAP ---
|
||||||
var shaders: SlotMap(ShaderID, GPUShader) = .init(alloc);
|
var shaders: KeyedSlotMap(ShaderID, GPUShader) = .init(alloc);
|
||||||
defer shaders.deinit();
|
defer shaders.deinit();
|
||||||
|
|
||||||
// --- NEW SHADER ---
|
// --- NEW SHADER ---
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ pub const log = @import("log.zig");
|
||||||
pub const ansi = @import("ansi.zig");
|
pub const ansi = @import("ansi.zig");
|
||||||
pub const Handle = @import("handle.zig").Handle;
|
pub const Handle = @import("handle.zig").Handle;
|
||||||
pub const SlotMap = @import("slot_map.zig").SlotMap;
|
pub const SlotMap = @import("slot_map.zig").SlotMap;
|
||||||
|
pub const KeyedSlotMap = @import("keyed_slot_map.zig").KeyedSlotMap;
|
||||||
pub const TypeID = @import("type_id.zig").of;
|
pub const TypeID = @import("type_id.zig").of;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
@ -49,11 +50,11 @@ test "SlotMap" {
|
||||||
//
|
//
|
||||||
|
|
||||||
// --- SHADER MAP ---
|
// --- SHADER MAP ---
|
||||||
var shaders: SlotMap(ShaderID, GPUShader) = .init(alloc);
|
var shaders: KeyedSlotMap(ShaderID, GPUShader) = .init(alloc);
|
||||||
defer shaders.deinit();
|
defer shaders.deinit();
|
||||||
|
|
||||||
// --- PIPELINE MAP ---
|
// --- PIPELINE MAP ---
|
||||||
var pipelines: SlotMap(PipelineKey, GPUPipeline) = .init(alloc);
|
var pipelines: KeyedSlotMap(PipelineKey, GPUPipeline) = .init(alloc);
|
||||||
defer pipelines.deinit();
|
defer pipelines.deinit();
|
||||||
|
|
||||||
// --- ADD MATERIALS ---
|
// --- ADD MATERIALS ---
|
||||||
|
|
@ -88,7 +89,7 @@ test "SlotMap" {
|
||||||
std.debug.print("┏━ SHADERS\n", .{});
|
std.debug.print("┏━ SHADERS\n", .{});
|
||||||
defer std.debug.print("┗━\n", .{});
|
defer std.debug.print("┗━\n", .{});
|
||||||
|
|
||||||
for (shaders.values.items) |entry| {
|
for (shaders.items()) |entry| {
|
||||||
const source = switch (entry.key) {
|
const source = switch (entry.key) {
|
||||||
.pbr => "assets/shaders/pbr.wgsl",
|
.pbr => "assets/shaders/pbr.wgsl",
|
||||||
.unlit => "assets/shaders/unlit.wgsl",
|
.unlit => "assets/shaders/unlit.wgsl",
|
||||||
|
|
|
||||||
133
src/keyed_slot_map.zig
Normal file
133
src/keyed_slot_map.zig
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const SlotMap = @import("slot_map.zig").SlotMap;
|
||||||
|
const Handle = @import("handle.zig").Handle;
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn KeyedSlotMap(
|
||||||
|
comptime K: type,
|
||||||
|
comptime V: type,
|
||||||
|
) type {
|
||||||
|
return struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub const Entry = struct {
|
||||||
|
key: K,
|
||||||
|
value: V,
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// FIELDS
|
||||||
|
//
|
||||||
|
|
||||||
|
// --- VALUES ---
|
||||||
|
slot_map: SlotMap(Entry),
|
||||||
|
lookup: std.AutoHashMap(K, Handle(V)),
|
||||||
|
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn init(alloc: std.mem.Allocator) Self {
|
||||||
|
return .{
|
||||||
|
.slot_map = .init(alloc),
|
||||||
|
.lookup = .init(alloc),
|
||||||
|
|
||||||
|
.alloc = alloc,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn deinit(self: *Self) void {
|
||||||
|
self.slot_map.deinit();
|
||||||
|
self.lookup.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn put(
|
||||||
|
self: *Self,
|
||||||
|
key: K,
|
||||||
|
value: V,
|
||||||
|
) error{ Duplicate, OutOfMemory }!Handle(V) {
|
||||||
|
// --- PREVENT DUPS ---
|
||||||
|
if (self.lookup.contains(key)) return error.Duplicate;
|
||||||
|
|
||||||
|
// --- RESULT ---
|
||||||
|
const handle = try self.slot_map.put(.{ .value = value, .key = key });
|
||||||
|
errdefer self.slot_map.remove(handle);
|
||||||
|
|
||||||
|
// --- NEW LOOKUP ---
|
||||||
|
try self.lookup.put(key, handle);
|
||||||
|
errdefer _ = self.lookup.remove(key);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn remove(
|
||||||
|
self: *Self,
|
||||||
|
handle: Handle(V),
|
||||||
|
) void {
|
||||||
|
// --- GET IDX ---
|
||||||
|
const idx: u32 = handle.idx;
|
||||||
|
|
||||||
|
// --- REMOVE FROM SLOTMAP ---
|
||||||
|
self.slot_map.remove(handle);
|
||||||
|
|
||||||
|
// --- REMOVE KEY ---
|
||||||
|
const key = self.values.items[idx].key;
|
||||||
|
_ = self.lookup.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn removeByKey(self: *Self, key: K) void {
|
||||||
|
const handle = self.lookup.get(key) orelse return;
|
||||||
|
_ = self.lookup.remove(key);
|
||||||
|
self.slot_map.remove(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn get(self: *Self, handle: Handle(V)) ?*V {
|
||||||
|
const entry = if (self.slot_map.get(handle)) |v| v else return null;
|
||||||
|
return &entry.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn getByKey(self: *Self, key: K) ?*V {
|
||||||
|
const handle = self.lookup.get(key) orelse return null;
|
||||||
|
return self.get(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn getHandle(self: *Self, key: K) ?Handle(V) {
|
||||||
|
return self.lookup.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn contains(self: *Self, key: K) bool {
|
||||||
|
return self.lookup.contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn count(self: *Self) u32 {
|
||||||
|
return self.lookup.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
/// ----------------------------------------------------
|
||||||
|
pub fn items(self: *Self) []Entry {
|
||||||
|
return self.slot_map.values.items;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -3,32 +3,22 @@ const Handle = @import("handle.zig").Handle;
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
pub fn SlotMap(
|
pub fn SlotMap(comptime T: type) type {
|
||||||
comptime K: type,
|
|
||||||
comptime V: type,
|
|
||||||
) type {
|
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
pub const Entry = struct {
|
|
||||||
key: K,
|
|
||||||
value: V,
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// FIELDS
|
// FIELDS
|
||||||
//
|
//
|
||||||
|
|
||||||
// --- VALUES ---
|
// --- VALUES ---
|
||||||
values: std.ArrayList(Entry),
|
values: std.ArrayList(T),
|
||||||
lookup: std.AutoHashMap(K, Handle(V)),
|
|
||||||
|
|
||||||
// --- LIFE TIMES ---
|
// --- LIFE TIMES ---
|
||||||
generations: std.ArrayList(u32),
|
generations: std.ArrayList(u32),
|
||||||
free_list: std.ArrayList(u32),
|
free_list: std.ArrayList(u32),
|
||||||
|
|
||||||
|
// --- MEMORY ---
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
|
|
@ -36,7 +26,6 @@ pub fn SlotMap(
|
||||||
pub fn init(alloc: std.mem.Allocator) Self {
|
pub fn init(alloc: std.mem.Allocator) Self {
|
||||||
return .{
|
return .{
|
||||||
.values = .empty,
|
.values = .empty,
|
||||||
.lookup = .init(alloc),
|
|
||||||
|
|
||||||
.generations = .empty,
|
.generations = .empty,
|
||||||
.free_list = .empty,
|
.free_list = .empty,
|
||||||
|
|
@ -49,7 +38,6 @@ pub fn SlotMap(
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
self.values.deinit(self.alloc);
|
self.values.deinit(self.alloc);
|
||||||
self.lookup.deinit();
|
|
||||||
self.generations.deinit(self.alloc);
|
self.generations.deinit(self.alloc);
|
||||||
self.free_list.deinit(self.alloc);
|
self.free_list.deinit(self.alloc);
|
||||||
}
|
}
|
||||||
|
|
@ -58,18 +46,11 @@ pub fn SlotMap(
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
pub fn put(
|
pub fn put(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
key: K,
|
value: T,
|
||||||
value: V,
|
) error{ Duplicate, OutOfMemory }!Handle(T) {
|
||||||
) error{ Duplicate, OutOfMemory }!Handle(V) {
|
|
||||||
// --- PREVENT DUPS ---
|
|
||||||
if (self.lookup.contains(key)) return error.Duplicate;
|
|
||||||
|
|
||||||
// --- NEW GENERATION ---
|
// --- NEW GENERATION ---
|
||||||
if (self.free_list.pop()) |idx| {
|
if (self.free_list.pop()) |idx| {
|
||||||
self.values.items[@intCast(idx)] = .{
|
self.values.items[@intCast(idx)] = value;
|
||||||
.key = key,
|
|
||||||
.value = value,
|
|
||||||
};
|
|
||||||
self.generations.items[@intCast(idx)] += 1;
|
self.generations.items[@intCast(idx)] += 1;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
|
|
@ -80,22 +61,15 @@ pub fn SlotMap(
|
||||||
|
|
||||||
// --- METADATA ---
|
// --- METADATA ---
|
||||||
const idx = self.values.items.len;
|
const idx = self.values.items.len;
|
||||||
const handle: Handle(V) = .{
|
const handle: Handle(T) = .{
|
||||||
.idx = @intCast(idx),
|
.idx = @intCast(idx),
|
||||||
.gen = 1,
|
.gen = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- NEW VALUE ---
|
// --- NEW VALUE ---
|
||||||
try self.values.append(self.alloc, .{
|
try self.values.append(self.alloc, value);
|
||||||
.value = value,
|
|
||||||
.key = key,
|
|
||||||
});
|
|
||||||
errdefer _ = self.values.swapRemove(idx);
|
errdefer _ = self.values.swapRemove(idx);
|
||||||
|
|
||||||
// --- NEW LOOKUP ---
|
|
||||||
try self.lookup.put(key, handle);
|
|
||||||
errdefer _ = self.lookup.remove(key);
|
|
||||||
|
|
||||||
// --- NEW GENERATION ---
|
// --- NEW GENERATION ---
|
||||||
try self.generations.append(self.alloc, 1);
|
try self.generations.append(self.alloc, 1);
|
||||||
|
|
||||||
|
|
@ -107,7 +81,7 @@ pub fn SlotMap(
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
pub fn remove(
|
pub fn remove(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
handle: Handle(V),
|
handle: Handle(T),
|
||||||
) void {
|
) void {
|
||||||
const idx: u32 = handle.idx;
|
const idx: u32 = handle.idx;
|
||||||
|
|
||||||
|
|
@ -115,10 +89,6 @@ pub fn SlotMap(
|
||||||
if (idx >= self.generations.items.len) return;
|
if (idx >= self.generations.items.len) return;
|
||||||
if (self.generations.items[idx] != handle.gen) return;
|
if (self.generations.items[idx] != handle.gen) return;
|
||||||
|
|
||||||
// --- REMOVE KEY ---
|
|
||||||
const key = self.values.items[idx].key;
|
|
||||||
_ = self.lookup.remove(key);
|
|
||||||
|
|
||||||
// --- GENERATION ---
|
// --- GENERATION ---
|
||||||
self.generations.items[idx] +|= 1;
|
self.generations.items[idx] +|= 1;
|
||||||
self.free_list.append(self.alloc, idx) catch unreachable;
|
self.free_list.append(self.alloc, idx) catch unreachable;
|
||||||
|
|
@ -126,44 +96,10 @@ pub fn SlotMap(
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
/// ----------------------------------------------------
|
/// ----------------------------------------------------
|
||||||
pub fn removeByKey(self: *Self, key: K) void {
|
pub fn get(self: *Self, handle: Handle(T)) ?*T {
|
||||||
const idx = self.lookup.get(key) orelse return;
|
|
||||||
_ = self.lookup.remove(key);
|
|
||||||
self.generations.items[idx] +|= 1;
|
|
||||||
self.free_list.append(self.alloc, idx) catch unreachable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
pub fn get(self: *Self, handle: Handle(V)) ?*V {
|
|
||||||
if (handle.idx >= self.values.items.len) return null;
|
if (handle.idx >= self.values.items.len) return null;
|
||||||
if (self.generations.items[handle.idx] != handle.gen) return null;
|
if (self.generations.items[handle.idx] != handle.gen) return null;
|
||||||
return &self.values.items[handle.idx].value;
|
return &self.values.items[handle.idx];
|
||||||
}
|
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
pub fn getByKey(self: *Self, key: K) ?*V {
|
|
||||||
const handle = self.lookup.get(key) orelse return null;
|
|
||||||
return self.get(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
pub fn getHandle(self: *Self, key: K) ?Handle(V) {
|
|
||||||
return self.lookup.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
pub fn contains(self: *Self, key: K) bool {
|
|
||||||
return self.lookup.contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
/// ----------------------------------------------------
|
|
||||||
pub fn count(self: *Self) u32 {
|
|
||||||
return self.lookup.count();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue