157 lines
4.2 KiB
Zig
157 lines
4.2 KiB
Zig
pub const SystemTaskRunner = struct {
|
|
allocator: std.mem.Allocator,
|
|
|
|
jobs: std.ArrayListUnmanaged(*SystemTask),
|
|
|
|
pub fn create(allocator: std.mem.Allocator) *@This() {
|
|
const self = allocator.create(@This());
|
|
|
|
self.* = .{
|
|
.allocator = allocator,
|
|
};
|
|
|
|
const Job = struct {
|
|
ctx: *SystemTaskRunner,
|
|
|
|
pub fn func(ctx: @This(), job: *core.JobContext) void {
|
|
_ = job;
|
|
_ = ctx;
|
|
|
|
while (true) {
|
|
// pump events
|
|
// if nothing pumped this frame, wait 100ms
|
|
if (self.jobs.items.len > 0) {
|
|
for (self.jobs.items) |j| {
|
|
_ = j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
try core.dispatchJob(Job{ .ctx = self });
|
|
|
|
return self;
|
|
}
|
|
|
|
pub fn pushJob(self: *@This()) !*SystemTask {
|
|
const task = try self.allocator.create(SystemTask);
|
|
try self.jobs.append(self.allocator, task);
|
|
}
|
|
|
|
// check completion from the task thread
|
|
// returns true if
|
|
pub fn checkCompletionTT(self: *@This(), task: *SystemTask) bool {
|
|
_ = task;
|
|
if (builtin.os.tag == .windows) {
|
|
_ = self;
|
|
}
|
|
}
|
|
|
|
pub fn destroy(self: *@This()) void {
|
|
self.allocator.destroy(self);
|
|
}
|
|
|
|
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "SystemTaskRunner");
|
|
};
|
|
|
|
pub const SystemTask = struct {
|
|
status: ExecutionStatus,
|
|
taskRunner: *SystemTaskRunner,
|
|
};
|
|
|
|
pub const SystemTaskExecution = struct {
|
|
task: *SystemTask,
|
|
|
|
pub fn deinit(self: *@This()) void {
|
|
if (core.getEngineObject(SystemTaskRunner)) |taskRunner| {
|
|
try taskRunner.pushJobRemoval(self.task);
|
|
}
|
|
}
|
|
};
|
|
|
|
pub const ExecutionStatus = enum {
|
|
ready,
|
|
failed,
|
|
success,
|
|
};
|
|
|
|
pub const Execution = struct {
|
|
mutex: std.Thread.Mutex = .{},
|
|
status: ExecutionStatus = .ready,
|
|
payload: ?*anyopaque = null,
|
|
command: std.ArrayListUnmanaged([]const u8) = .{},
|
|
outputStream: std.ArrayListUnmanaged(u8) = .{},
|
|
backing: std.mem.Allocator,
|
|
arena: std.heap.ArenaAllocator,
|
|
child: ?std.process.Child,
|
|
|
|
lastUpdateTime: i64 = 0,
|
|
timeout: i64 = 1000000000,
|
|
|
|
pub fn startAlloc(allocator: std.mem.Allocator, command: []const []const u8) !*@This() {
|
|
const self = try allocator.create(@This());
|
|
self.* = .{
|
|
.command = undefined,
|
|
.backing = allocator,
|
|
.arena = std.heap.ArenaAllocator.init(allocator),
|
|
};
|
|
|
|
const alloc = self.arena.allocator();
|
|
for (command) |arg| {
|
|
const a = try alloc.dupe(u8, arg);
|
|
try self.command.append(alloc, a);
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
pub fn run(self: *@This()) void {
|
|
self.child = std.process.Child.init(self.command.items, self.arena.allocator());
|
|
self.child.?.spawn();
|
|
}
|
|
|
|
pub fn clearOutputStream(self: *@This()) void {
|
|
self.outputStream.clearRetainingCapacity();
|
|
}
|
|
|
|
// returns true if the status changed at all
|
|
// can access output via Execution.outputStream
|
|
pub fn tick(self: *@This()) bool {
|
|
const lastStatus = self.status;
|
|
_ = lastStatus;
|
|
const lastOutputStreamLen = self.outputStream.len;
|
|
var rv: bool = false;
|
|
|
|
// const allocator = self.arena.allocator();
|
|
// try self.child.?.collectOutput(allocator, &self.outputStream, &self.outputStream, 8192 * 2);
|
|
|
|
if (lastOutputStreamLen != self.outputStream.len) {
|
|
self.lastUpdateTime = std.time.microTimestamp();
|
|
rv = true;
|
|
}
|
|
|
|
const ts = std.time.microTimestamp();
|
|
|
|
if (self.lastUpdateTime - self.timeout > ts) {}
|
|
|
|
if (self.child.?) {}
|
|
|
|
return rv;
|
|
}
|
|
|
|
pub fn start(command: []const []const u8) !*@This() {
|
|
return try startAlloc(sys.getAllocator(), command);
|
|
}
|
|
|
|
pub fn destroy(self: *@This()) void {
|
|
self.arena.deinit();
|
|
self.backing.destroy(self);
|
|
}
|
|
};
|
|
|
|
const std = @import("std");
|
|
pub const core = @import("core");
|
|
const sys = @import("../sys.zig");
|
|
const builtin = @import("builtin");
|