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
|
const std = @import("std");
pub fn Scheduler(function: anytype) type {
const FuncType = @TypeOf(function);
const func_info = @typeInfo(FuncType).Fn;
const R = func_info.return_type orelse std.builtin.Type.Void;
const ArgType = std.meta.ArgsTuple(FuncType);
const wrapper = struct {
pub fn call(args: ArgType, result: *R) void {
result.* = @call(.auto, function, args);
}
}.call;
return struct {
const Self = @This();
allocator: std.mem.Allocator,
pool: std.Thread.Pool,
wait_group: std.Thread.WaitGroup,
results: std.ArrayList(*R),
pub fn init(self: *Self, allocator: std.mem.Allocator) !void {
self.allocator = allocator;
self.results = std.ArrayList(*R).init(allocator);
self.wait_group.reset();
try self.pool.init(.{
.allocator = allocator,
});
}
pub fn push_task(self: *Self, args: ArgType) !void {
const result = try self.allocator.create(R);
try self.results.append(result);
self.pool.spawnWg(
&self.wait_group,
wrapper,
.{ args, result }
);
}
pub fn deinit(self: *Self) ![]R {
self.pool.waitAndWork(&self.wait_group);
self.pool.deinit();
const results = try self.allocator.alloc(R, self.results.items.len);
for (self.results.items, 0..) |result, index| {
results[index] = result.*;
self.allocator.destroy(result);
}
self.results.deinit();
self.* = undefined;
return results;
}
};
}
|