1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
const std = @import("std");
const Allocator = std.mem.Allocator;
const components = @import("components.zig");
const sparse = @import("sparse.zig");
const Renderer = @import("renderer");
const Input = @import("sideros").Input;
const ecs = @import("ecs.zig");
pub const System = ecs.System;
pub const SystemGroup = []const System;
pub const SyncGroup = []const System;
pub const Resources = struct {
window: Renderer.Window,
renderer: Renderer,
input: Input,
delta_time: f64 = 0.0,
};
pub const Human = struct {
position: components.Position,
speed: components.Speed,
};
// TODO(ernesto): Move pool to its own file
pub const Pool = struct {
humans: std.MultiArrayList(Human),
resources: Resources,
allocator: Allocator,
system_groups: std.ArrayList(SystemGroup),
sync_groups: std.ArrayList(SyncGroup),
thread_pool: *std.Thread.Pool,
wait_group: std.Thread.WaitGroup,
mutex: std.Thread.Mutex,
pub fn init(allocator: Allocator, resources: Resources) !@This() {
var pool = @This(){
.humans = .{},
.resources = resources,
.system_groups = std.ArrayList(SystemGroup).init(allocator),
.sync_groups = std.ArrayList(SystemGroup).init(allocator),
.thread_pool = try allocator.create(std.Thread.Pool),
.wait_group = .{},
.mutex = .{},
.allocator = allocator,
};
try pool.thread_pool.init(.{
.allocator = allocator,
.n_jobs = 4,
});
return pool;
}
pub fn addSystemGroup(self: *@This(), group: SystemGroup, sync: bool) !void {
if (sync) {
try self.sync_groups.append(group);
} else {
try self.system_groups.append(group);
}
}
pub fn deinit(self: *@This()) void {
self.humans.deinit(self.allocator);
self.system_groups.deinit();
self.sync_groups.deinit();
self.thread_pool.deinit();
self.allocator.destroy(self.thread_pool);
}
pub fn tick(self: *@This()) void {
for (0..self.system_groups.items.len) |i| {
self.thread_pool.spawnWg(&self.wait_group, struct {
fn run(pool: *Pool, index: usize) void {
const group = pool.system_groups.items[index];
for (group) |system| {
// TODO: system errors should be correctly handled
system(pool) catch unreachable;
}
}
}.run, .{ self, i });
}
for (0..self.sync_groups.items.len) |i| {
const group = self.sync_groups.items[i];
for (group) |system| {
system(self) catch unreachable;
}
}
}
fn getEntities(self: *@This(), T: type) *std.MultiArrayList(T) {
return switch (T) {
Human => &self.humans,
else => unreachable,
};
}
pub fn createEntity(self: *@This(), entity: anytype) !usize {
var list = self.getEntities(@TypeOf(entity));
const index = list.len;
try list.append(self.allocator, entity);
return index;
}
pub fn destroyEntity(self: *@This(), comptime T: type, entity: usize) void {
self.getEntities(T).swapRemove(entity);
}
};
|