Skip to content

Instantly share code, notes, and snippets.

@DutchGhost
Created December 29, 2020 21:04
Show Gist options
  • Select an option

  • Save DutchGhost/d226c59707962758d4c598ff1fda8184 to your computer and use it in GitHub Desktop.

Select an option

Save DutchGhost/d226c59707962758d4c598ff1fda8184 to your computer and use it in GitHub Desktop.
async mutex
const std = @import("std");
const Node = struct {
next: ?*Node = null,
frame: anyframe = undefined,
};
const List = struct {
const Self = @This();
next: ?*Node = null,
fn pop(self: *Self) ?*Node {
const head = self.next orelse return null;
self.next = head.next;
return head;
}
fn push(self: *Self, node: *Node) void {
node.next = self.next;
self.next = node;
}
};
const Mutex = struct {
const Self = @This();
const State = enum(u8) {
Locked,
Unlocked,
};
const Guard = struct {
mutex: *Mutex,
pub fn release(self: *Guard) void {
@atomicStore(State, &self.mutex.state, .Unlocked, .Release);
if (self.mutex.waiters.pop()) |node| {
resume node.frame;
}
}
};
state: State = State.Unlocked,
waiters: List = List {},
pub fn init() Self {
return .{};
}
pub fn lock(self: *Self) Guard {
var node = Node {.frame = @frame()};
while(true) {
switch (@atomicRmw(State, &self.state, .Xchg, .Locked, .Acquire)) {
.Unlocked => return Guard{ .mutex = self },
.Locked => { suspend self.waiters.push(&node); },
}
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment