feat: implement a 2-way channel for message passing
This commit is contained in:
parent
52ac8d952f
commit
d5e66caf21
33
src/lib.zig
33
src/lib.zig
|
@ -1,8 +1,29 @@
|
|||
const std = @import("std");
|
||||
|
||||
const Log2Int = std.math.Log2Int;
|
||||
|
||||
pub fn Channel(comptime T: type) type {
|
||||
const EmuMessage = enum { Pause, Resume, Quit };
|
||||
const GuiMessage = enum { Paused, Quit };
|
||||
|
||||
pub const TwoWayChannel = struct {
|
||||
const Self = @This();
|
||||
|
||||
emu: Channel(EmuMessage),
|
||||
gui: Channel(GuiMessage),
|
||||
|
||||
pub fn init(items: []u8) Self {
|
||||
comptime std.debug.assert(@sizeOf(EmuMessage) == @sizeOf(GuiMessage));
|
||||
comptime std.debug.assert(@sizeOf(@typeInfo([]u8).Pointer.child) == @sizeOf(EmuMessage));
|
||||
|
||||
std.debug.assert(items.len % 2 == 0);
|
||||
|
||||
const left = @ptrCast([*]EmuMessage, items)[0 .. items.len / 2];
|
||||
const right = @ptrCast([*]GuiMessage, items)[items.len / 2 .. items.len];
|
||||
|
||||
return .{ .emu = Channel(EmuMessage).init(left), .gui = Channel(GuiMessage).init(right) };
|
||||
}
|
||||
};
|
||||
|
||||
fn Channel(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
const Index = usize;
|
||||
|
@ -29,12 +50,12 @@ pub fn Channel(comptime T: type) type {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn push(self: *Self, value: T) Error!void {
|
||||
pub fn push(self: *Self, value: T) void {
|
||||
const read_idx = self.read.load(.Acquire);
|
||||
const write_idx = self.write.load(.Acquire);
|
||||
|
||||
// Check to see if Queue is full
|
||||
if (write_idx - read_idx == self.buf.len) return Error.buffer_full;
|
||||
if (write_idx - read_idx == self.buf.len) @panic("Channel: Buffer is full");
|
||||
|
||||
self.buf[self.mask(write_idx)] = value;
|
||||
|
||||
|
@ -49,7 +70,7 @@ pub fn Channel(comptime T: type) type {
|
|||
if (read_idx == write_idx) return null;
|
||||
|
||||
std.atomic.fence(.Acquire);
|
||||
const value = self.buf[self.mask(self.read)];
|
||||
const value = self.buf[self.mask(read_idx)];
|
||||
|
||||
std.atomic.fence(.Release);
|
||||
self.read.store(read_idx + 1, .Release);
|
||||
|
@ -159,4 +180,4 @@ pub inline fn rotr(comptime T: type, x: T, r: anytype) T {
|
|||
|
||||
const ar = @intCast(Log2Int(T), @mod(r, @typeInfo(T).Int.bits));
|
||||
return x >> ar | x << (1 +% ~ar);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue