The channel works fine for the first send/receiver then it proceeds to do unwanted behavior
Channel:
pub const TaggedHead = extern struct {
index: usize = 0,
tag: usize = 0,
};
pub fn Channel(comptime T: type, comptime capacity: usize) type {
return struct {
const Self = @This();
head: Atomic(*TaggedHead),
tail: Atomic(usize),
buffer: [capacity]T = undefined,
pub fn init(self: *Self, empty_tagged_head: *TaggedHead) void {
self.head = Atomic(*TaggedHead).init(empty_tagged_head);
self.tail = Atomic(usize).init(0);
}
pub fn send(self: *Self, value: T) !void {
var old_tail = self.tail.load(.monotonic);
var new_tail: usize = undefined;
while (true) {
new_tail = (old_tail + 1) % capacity;
if (new_tail == self.head.load(.monotonic).index) {
return error.ChannelFull;
}
old_tail = self.tail.cmpxchgWeak(old_tail, new_tail, .release, .monotonic) orelse break;
}
self.buffer[old_tail] = value;
self.tail.store(new_tail, .release);
}
pub fn recv(self: *Self) ?T {
var old_tagged_head = self.head.load(.acquire);
while (true) {
if (old_tagged_head.index == self.tail.load(.monotonic)) {
return null;
}
var new_head = TaggedHead{
.index = (old_tagged_head.index + 1) % capacity,
.tag = old_tagged_head.tag + 1,
};
old_tagged_head = self.head.cmpxchgWeak(old_tagged_head, &new_head, .acquire, .monotonic) orelse {
const value = self.buffer[old_tagged_head.index];
return value;
};
}
}
};
}
