Merge pull request #16 from RUSshy/master

Fix memory leak #15
master
prime31 3 years ago committed by GitHub
commit 0d89c0e255

@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const registry = @import("registry.zig");
/// generates versioned "handles" (https://floooh.github.io/2018/06/17/handles-vs-pointers.html) /// generates versioned "handles" (https://floooh.github.io/2018/06/17/handles-vs-pointers.html)
/// you choose the type of the handle (aka its size) and how much of that goes to the index and the version. /// you choose the type of the handle (aka its size) and how much of that goes to the index and the version.
@ -38,7 +39,6 @@ pub fn Handles(comptime HandleType: type, comptime IndexType: type, comptime Ver
return h; return h;
} }
} }
return null; return null;
} }
}; };
@ -59,15 +59,15 @@ pub fn Handles(comptime HandleType: type, comptime IndexType: type, comptime Ver
} }
pub fn extractId(_: Self, handle: HandleType) IndexType { pub fn extractId(_: Self, handle: HandleType) IndexType {
return @truncate(IndexType, handle); return @truncate(IndexType, handle & registry.entity_traits.entity_mask);
} }
pub fn extractVersion(_: Self, handle: HandleType) VersionType { pub fn extractVersion(_: Self, handle: HandleType) VersionType {
return @truncate(VersionType, handle >> @bitSizeOf(IndexType)); return @truncate(VersionType, handle >> registry.entity_traits.entity_shift);
} }
fn forge(id: IndexType, version: VersionType) HandleType { fn forge(id: IndexType, version: VersionType) HandleType {
return id | @as(HandleType, version) << @bitSizeOf(IndexType); return id | @as(HandleType, version) << registry.entity_traits.entity_shift;
} }
pub fn create(self: *Self) HandleType { pub fn create(self: *Self) HandleType {

@ -10,7 +10,7 @@ const TypeStore = @import("type_store.zig").TypeStore;
// allow overriding EntityTraits by setting in root via: EntityTraits = EntityTraitsType(.medium); // allow overriding EntityTraits by setting in root via: EntityTraits = EntityTraitsType(.medium);
const root = @import("root"); const root = @import("root");
const entity_traits = if (@hasDecl(root, "EntityTraits")) root.EntityTraits.init() else @import("entity.zig").EntityTraits.init(); pub const entity_traits = if (@hasDecl(root, "EntityTraits")) root.EntityTraits.init() else @import("entity.zig").EntityTraits.init();
// setup the Handles type based on the type set in EntityTraits // setup the Handles type based on the type set in EntityTraits
const EntityHandles = Handles(entity_traits.entity_type, entity_traits.index_type, entity_traits.version_type); const EntityHandles = Handles(entity_traits.entity_type, entity_traits.index_type, entity_traits.version_type);
@ -261,7 +261,7 @@ pub const Registry = struct {
/// Returns the version stored along with an entity identifier /// Returns the version stored along with an entity identifier
pub fn version(_: *Registry, entity: Entity) entity_traits.version_type { pub fn version(_: *Registry, entity: Entity) entity_traits.version_type {
return @truncate(entity_traits.version_type, entity >> @bitSizeOf(entity_traits.index_type)); return @truncate(entity_traits.version_type, entity >> entity_traits.entity_shift);
} }
/// Creates a new entity and returns it /// Creates a new entity and returns it

@ -1,14 +1,14 @@
const std = @import("std"); const std = @import("std");
const warn = std.debug.warn; const warn = std.debug.warn;
const utils = @import("utils.zig"); const utils = @import("utils.zig");
const registry = @import("registry.zig");
const ReverseSliceIterator = @import("utils.zig").ReverseSliceIterator; const ReverseSliceIterator = @import("utils.zig").ReverseSliceIterator;
// TODO: fix entity_mask. it should come from EntityTraitsDefinition. // TODO: fix entity_mask. it should come from EntityTraitsDefinition.
pub fn SparseSet(comptime SparseT: type) type { pub fn SparseSet(comptime SparseT: type) type {
return struct { return struct {
const Self = @This(); const Self = @This();
const page_size: usize = 32768; const page_size: usize = 4096;
const entity_per_page = page_size / @sizeOf(SparseT);
sparse: std.ArrayList(?[]SparseT), sparse: std.ArrayList(?[]SparseT),
dense: std.ArrayList(SparseT), dense: std.ArrayList(SparseT),
@ -17,9 +17,9 @@ pub fn SparseSet(comptime SparseT: type) type {
pub fn initPtr(allocator: *std.mem.Allocator) *Self { pub fn initPtr(allocator: *std.mem.Allocator) *Self {
var set = allocator.create(Self) catch unreachable; var set = allocator.create(Self) catch unreachable;
set.sparse = std.ArrayList(?[]SparseT).init(allocator); set.sparse = std.ArrayList(?[]SparseT).initCapacity(allocator, 16) catch unreachable;
set.dense = std.ArrayList(SparseT).init(allocator); set.dense = std.ArrayList(SparseT).initCapacity(allocator, 16) catch unreachable;
set.entity_mask = std.math.maxInt(SparseT); set.entity_mask = registry.entity_traits.entity_mask;
set.allocator = allocator; set.allocator = allocator;
return set; return set;
} }
@ -28,7 +28,7 @@ pub fn SparseSet(comptime SparseT: type) type {
return Self{ return Self{
.sparse = std.ArrayList(?[]SparseT).init(allocator), .sparse = std.ArrayList(?[]SparseT).init(allocator),
.dense = std.ArrayList(SparseT).init(allocator), .dense = std.ArrayList(SparseT).init(allocator),
.entity_mask = std.math.maxInt(SparseT), .entity_mask = registry.entity_traits.entity_mask,
.allocator = null, .allocator = null,
}; };
} }
@ -50,11 +50,11 @@ pub fn SparseSet(comptime SparseT: type) type {
} }
pub fn page(self: Self, sparse: SparseT) usize { pub fn page(self: Self, sparse: SparseT) usize {
return (sparse & self.entity_mask) / entity_per_page; return (sparse & self.entity_mask) / page_size;
} }
fn offset(_: Self, sparse: SparseT) usize { fn offset(_: Self, sparse: SparseT) usize {
return sparse & (entity_per_page - 1); return sparse & (page_size - 1);
} }
fn assure(self: *Self, pos: usize) []SparseT { fn assure(self: *Self, pos: usize) []SparseT {
@ -65,14 +65,12 @@ pub fn SparseSet(comptime SparseT: type) type {
std.mem.set(?[]SparseT, self.sparse.items[start_pos..], null); std.mem.set(?[]SparseT, self.sparse.items[start_pos..], null);
} }
if (self.sparse.items[pos]) |arr| { if (self.sparse.items[pos] == null) {
return arr; var new_page = self.sparse.allocator.alloc(SparseT, page_size) catch unreachable;
std.mem.set(SparseT, new_page, std.math.maxInt(SparseT));
self.sparse.items[pos] = new_page;
} }
var new_page = self.sparse.allocator.alloc(SparseT, entity_per_page) catch unreachable;
std.mem.set(SparseT, new_page, std.math.maxInt(SparseT));
self.sparse.items[pos] = new_page;
return self.sparse.items[pos].?; return self.sparse.items[pos].?;
} }
@ -105,7 +103,9 @@ pub fn SparseSet(comptime SparseT: type) type {
pub fn contains(self: Self, sparse: SparseT) bool { pub fn contains(self: Self, sparse: SparseT) bool {
const curr = self.page(sparse); const curr = self.page(sparse);
return curr < self.sparse.items.len and self.sparse.items[curr] != null and self.sparse.items[curr].?[self.offset(sparse)] != std.math.maxInt(SparseT); return curr < self.sparse.items.len and
self.sparse.items[curr] != null and
self.sparse.items[curr].?[self.offset(sparse)] != std.math.maxInt(SparseT);
} }
/// Returns the position of an entity in a sparse set /// Returns the position of an entity in a sparse set

Loading…
Cancel
Save