101 lines
3.1 KiB
Zig
101 lines
3.1 KiB
Zig
const std = @import("std");
|
|
|
|
/// Processes are run by the Scheduler. They use a similar pattern to Allocators in that they are created and
|
|
/// added as fields in a parent struct, your actual process that will be run.
|
|
pub const Process = struct {
|
|
const State = enum(u8) { uninitialized, running, paused, succeeded, failed, aborted, finished };
|
|
|
|
updateFn: *const fn (self: *Process) void,
|
|
startFn: ?*const fn (self: *Process) void = null,
|
|
abortedFn: ?*const fn (self: *Process) void = null,
|
|
failedFn: ?*const fn (self: *Process) void = null,
|
|
succeededFn: ?*const fn (self: *Process) void = null,
|
|
deinit: *const fn (self: *Process, allocator: std.mem.Allocator) void = undefined,
|
|
|
|
state: State = .uninitialized,
|
|
stopped: bool = false,
|
|
next: ?*Process = null,
|
|
|
|
pub fn getParent(self: *Process, comptime T: type) *T {
|
|
return @fieldParentPtr(T, "process", self);
|
|
}
|
|
|
|
/// Terminates a process with success if it's still alive
|
|
pub fn succeed(self: *Process) void {
|
|
if (self.alive()) self.state = .succeeded;
|
|
}
|
|
|
|
/// Terminates a process with errors if it's still alive
|
|
pub fn fail(self: *Process) void {
|
|
if (self.alive()) self.state = .failed;
|
|
}
|
|
|
|
/// Stops a process if it's in a running state
|
|
pub fn pause(self: *Process) void {
|
|
if (self.state == .running) self.state = .paused;
|
|
}
|
|
|
|
/// Restarts a process if it's paused
|
|
pub fn unpause(self: *Process) void {
|
|
if (self.state == .paused) self.state = .running;
|
|
}
|
|
|
|
/// Aborts a process if it's still alive
|
|
pub fn abort(self: *Process, immediately: bool) void {
|
|
if (self.alive()) {
|
|
self.state = .aborted;
|
|
|
|
if (immediately) {
|
|
self.tick();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Returns true if a process is either running or paused
|
|
pub fn alive(self: Process) bool {
|
|
return self.state == .running or self.state == .paused;
|
|
}
|
|
|
|
/// Returns true if a process is already terminated
|
|
pub fn dead(self: Process) bool {
|
|
return self.state == .finished;
|
|
}
|
|
|
|
pub fn rejected(self: Process) bool {
|
|
return self.stopped;
|
|
}
|
|
|
|
/// Updates a process and its internal state
|
|
pub fn tick(self: *Process) void {
|
|
switch (self.state) {
|
|
.uninitialized => {
|
|
if (self.startFn) |func| func(self);
|
|
self.state = .running;
|
|
},
|
|
.running => {
|
|
self.updateFn(self);
|
|
},
|
|
else => {},
|
|
}
|
|
|
|
// if it's dead, it must be notified and removed immediately
|
|
switch (self.state) {
|
|
.succeeded => {
|
|
if (self.succeededFn) |func| func(self);
|
|
self.state = .finished;
|
|
},
|
|
.failed => {
|
|
if (self.failedFn) |func| func(self);
|
|
self.state = .finished;
|
|
self.stopped = true;
|
|
},
|
|
.aborted => {
|
|
if (self.abortedFn) |func| func(self);
|
|
self.state = .finished;
|
|
self.stopped = true;
|
|
},
|
|
else => {},
|
|
}
|
|
}
|
|
};
|