Created
December 29, 2020 21:04
-
-
Save DutchGhost/d226c59707962758d4c598ff1fda8184 to your computer and use it in GitHub Desktop.
async mutex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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