authorgravatar for 45520026+kprotty@users.noreply.github.comkprotty <45520026+kprotty@users.noreply.github.com> 2020-09-28 07:25:51-05:00
committergravatar for 45520026+kprotty@users.noreply.github.comkprotty <45520026+kprotty@users.noreply.github.com> 2020-09-28 07:25:51-05:00
log468a4bf0b443067b9d4a0bf68ea7e675a9bca727
treecd7c373e2e0077f237f158c96db166bc42a9cdc1
parenta31d9f92f282a878836a3ecac5a48d5f4037868c

address some review changes


1 files changed, 21 insertions(+), 4 deletions(-)

lib/std/event/lock.zig+21-4
...@@ -20,13 +20,14 @@ pub const Lock = struct {...@@ -20,13 +20,14 @@ pub const Lock = struct {
20 head: usize = UNLOCKED,20 head: usize = UNLOCKED,
2121
22 const UNLOCKED = 0;22 const UNLOCKED = 0;
23 const LOCKED = 69;23 const LOCKED = 1;
2424
25 const global_event_loop = Loop.instance orelse25 const global_event_loop = Loop.instance orelse
26 @compileError("std.event.Lock currently only works with event-based I/O");26 @compileError("std.event.Lock currently only works with event-based I/O");
2727
28 const Waiter = struct {28 const Waiter = struct {
29 next: ?*Waiter,29 // forced Waiter alignment to ensure it doesn't clash with LOCKED
30 next: ?*Waiter align(2),
30 tail: *Waiter,31 tail: *Waiter,
31 node: Loop.NextTickNode,32 node: Loop.NextTickNode,
32 };33 };
...@@ -34,6 +35,14 @@ pub const Lock = struct {...@@ -34,6 +35,14 @@ pub const Lock = struct {
34 pub fn acquire(self: *Lock) Held {35 pub fn acquire(self: *Lock) Held {
35 const held = self.mutex.acquire();36 const held = self.mutex.acquire();
3637
38 // self.head transitions from multiple stages depending on the value:
39 // UNLOCKED -> LOCKED:
40 // acquire Lock ownership when theres no waiters
41 // LOCKED -> <Waiter head ptr>:
42 // Lock is already owned, enqueue first Waiter
43 // <head ptr> -> <head ptr>:
44 // Lock is owned with pending waiters. Push our waiter to the queue.
45
37 if (self.head == UNLOCKED) {46 if (self.head == UNLOCKED) {
38 self.head = LOCKED;47 self.head = LOCKED;
39 held.release();48 held.release();
...@@ -47,7 +56,7 @@ pub const Lock = struct {...@@ -47,7 +56,7 @@ pub const Lock = struct {
47 const head = switch (self.head) {56 const head = switch (self.head) {
48 UNLOCKED => unreachable,57 UNLOCKED => unreachable,
49 LOCKED => null,58 LOCKED => null,
50 else => @intToPtr(?*Waiter, self.head),59 else => @intToPtr(*Waiter, self.head),
51 };60 };
5261
53 if (head) |h| {62 if (head) |h| {
...@@ -77,9 +86,17 @@ pub const Lock = struct {...@@ -77,9 +86,17 @@ pub const Lock = struct {
77 const held = self.lock.mutex.acquire();86 const held = self.lock.mutex.acquire();
78 defer held.release();87 defer held.release();
7988
89 // self.head goes through the reverse transition from acquire():
90 // <head ptr> -> <new head ptr>:
91 // pop a waiter from the queue to give Lock ownership when theres still others pending
92 // <head ptr> -> LOCKED:
93 // pop the laster waiter from the queue, while also giving it lock ownership when awaken
94 // LOCKED -> UNLOCKED:
95 // last lock owner releases lock while no one else is waiting for it
96
80 switch (self.lock.head) {97 switch (self.lock.head) {
81 UNLOCKED => {98 UNLOCKED => {
82 std.debug.panic("Lock unlocked when already unlocked", .{});99 unreachable; // Lock unlocked while unlocking
83 },100 },
84 LOCKED => {101 LOCKED => {
85 self.lock.head = UNLOCKED;102 self.lock.head = UNLOCKED;