Switch to using OS pipes
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
const CharDev = std.atomic.Queue(i32);
|
||||
// We're using pipes as character devices
|
||||
pub const CharDev = [2]i32;
|
||||
|
||||
pub fn loadFromStream(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) anyerror![]i32 {
|
||||
var program = try alloc.alloc(i32, 1024);
|
||||
@@ -111,8 +112,8 @@ pub const Machine = struct {
|
||||
return Machine{
|
||||
.alloc = alloc,
|
||||
.memory = program,
|
||||
.input = CharDev.init(),
|
||||
.output = CharDev.init(),
|
||||
.input = try std.os.pipe(),
|
||||
.output = try std.os.pipe(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -121,47 +122,43 @@ pub const Machine = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Machine) void {
|
||||
// TODO
|
||||
std.os.close(self.input[0]);
|
||||
std.os.close(self.input[1]);
|
||||
std.os.close(self.output[0]);
|
||||
std.os.close(self.output[1]);
|
||||
}
|
||||
|
||||
pub fn readFromInput(self: *Machine, blocking: bool) !i32 {
|
||||
return self.__in(&self.input, blocking);
|
||||
pub fn readFromInput(self: *Machine) !i32 {
|
||||
return self.__in(self.input);
|
||||
}
|
||||
|
||||
pub fn writeToInput(self: *Machine, val: i32) !void {
|
||||
return self.__out(&self.input, val);
|
||||
return self.__out(self.input, val);
|
||||
}
|
||||
|
||||
pub fn readFromOutput(self: *Machine, blocking: bool) !i32 {
|
||||
return self.__in(&self.output, blocking);
|
||||
pub fn readFromOutput(self: *Machine) !i32 {
|
||||
return self.__in(self.output);
|
||||
}
|
||||
|
||||
pub fn writeToOutput(self: *Machine, val: i32) !void {
|
||||
return self.__out(&self.output, val);
|
||||
return self.__out(self.output, val);
|
||||
}
|
||||
|
||||
inline fn __in(self: *Machine, dev: *CharDev, blocking: bool) !i32 {
|
||||
var node = dev.get();
|
||||
inline fn __in(self: *Machine, dev: CharDev) !i32 {
|
||||
const fd = dev[0]; // Read from the pipe
|
||||
var store: [4]u8 = undefined;
|
||||
|
||||
if (node == null) {
|
||||
if (!blocking) return std.os.ReadError.WouldBlock;
|
||||
// Just busy-wait for now
|
||||
while (node == null) node = dev.get();
|
||||
}
|
||||
var n = try std.os.read(fd, &store);
|
||||
std.debug.assert(n == 4); // TODO: handle partial reads
|
||||
|
||||
if (node) |n| {
|
||||
defer self.alloc.destroy(n);
|
||||
return n.data;
|
||||
}
|
||||
|
||||
unreachable;
|
||||
return std.mem.readIntNative(i32, &store);
|
||||
}
|
||||
|
||||
inline fn __out(self: *Machine, dev: *CharDev, val: i32) !void {
|
||||
var node = try self.alloc.create(CharDev.Node);
|
||||
node.data = val;
|
||||
inline fn __out(self: *Machine, dev: CharDev, val: i32) !void {
|
||||
const fd = dev[1]; // Write to the pipe
|
||||
const bytes = std.mem.asBytes(&val);
|
||||
|
||||
dev.put(node);
|
||||
try std.os.write(fd, bytes);
|
||||
}
|
||||
|
||||
/// Read an immediate or position value from memory. Parameter determines
|
||||
@@ -200,7 +197,7 @@ pub const Machine = struct {
|
||||
},
|
||||
|
||||
.IN => {
|
||||
self.__write(0, try self.readFromInput(true)); // blocking read
|
||||
self.__write(0, try self.readFromInput()); // blocking read
|
||||
},
|
||||
|
||||
.OUT => {
|
||||
@@ -301,7 +298,7 @@ test "day 5 example 1" {
|
||||
try machine.run();
|
||||
|
||||
assert(std.mem.eql(i32, before[0..before.len], after[0..after.len]));
|
||||
assert(666 == try machine.readFromOutput(false));
|
||||
assert(666 == try machine.readFromOutput());
|
||||
}
|
||||
|
||||
test "Instruction#decode ADD" {
|
||||
|
Reference in New Issue
Block a user