authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-23 20:35:53-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-23 20:49:38-07:00
logc2b1c8895334c4b597a665c2e8e29ce4a103f5b4
treeba71d00181c0e3dfd323e953f9a7d2b6e1301b2e
parent177377b6e356b34bbed40cadca596658d158af6b

std: fix compile errors introduced in previous commit


4 files changed, 33 insertions(+), 32 deletions(-)

lib/std/StaticResetEvent.zig+1-1
...@@ -105,7 +105,7 @@ pub const DebugEvent = struct {...@@ -105,7 +105,7 @@ pub const DebugEvent = struct {
105 }105 }
106 }106 }
107107
108 fn timedWait(ev: *DebugEvent, timeout: u64) TimedWaitResult {108 pub fn timedWait(ev: *DebugEvent, timeout: u64) TimedWaitResult {
109 switch (ev.state) {109 switch (ev.state) {
110 .unset => return .timed_out,110 .unset => return .timed_out,
111 .set => return .event_set,111 .set => return .event_set,
lib/std/auto_reset_event.zig+21-22
...@@ -7,14 +7,15 @@ const std = @import("std.zig");...@@ -7,14 +7,15 @@ const std = @import("std.zig");
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const testing = std.testing;8const testing = std.testing;
9const assert = std.debug.assert;9const assert = std.debug.assert;
10const StaticResetEvent = std.StaticResetEvent;
1011
11/// Similar to std.ResetEvent but on `set()` it also (atomically) does `reset()`.12/// Similar to `StaticResetEvent` but on `set()` it also (atomically) does `reset()`.
12/// Unlike std.ResetEvent, `wait()` can only be called by one thread (MPSC-like).13/// Unlike StaticResetEvent, `wait()` can only be called by one thread (MPSC-like).
13pub const AutoResetEvent = struct {14pub const AutoResetEvent = struct {
14 /// AutoResetEvent has 3 possible states:15 /// AutoResetEvent has 3 possible states:
15 /// - UNSET: the AutoResetEvent is currently unset16 /// - UNSET: the AutoResetEvent is currently unset
16 /// - SET: the AutoResetEvent was notified before a wait() was called17 /// - SET: the AutoResetEvent was notified before a wait() was called
17 /// - <std.ResetEvent pointer>: there is an active waiter waiting for a notification.18 /// - <StaticResetEvent pointer>: there is an active waiter waiting for a notification.
18 ///19 ///
19 /// When attempting to wait:20 /// When attempting to wait:
20 /// if the event is unset, it registers a ResetEvent pointer to be notified when the event is set21 /// if the event is unset, it registers a ResetEvent pointer to be notified when the event is set
...@@ -25,20 +26,20 @@ pub const AutoResetEvent = struct {...@@ -25,20 +26,20 @@ pub const AutoResetEvent = struct {
25 /// if theres a waiting ResetEvent, then we unset the event and notify the ResetEvent26 /// if theres a waiting ResetEvent, then we unset the event and notify the ResetEvent
26 ///27 ///
27 /// This ensures that the event is automatically reset after a wait() has been issued28 /// This ensures that the event is automatically reset after a wait() has been issued
28 /// and avoids the race condition when using std.ResetEvent in the following scenario:29 /// and avoids the race condition when using StaticResetEvent in the following scenario:
29 /// thread 1 | thread 230 /// thread 1 | thread 2
30 /// std.ResetEvent.wait() |31 /// StaticResetEvent.wait() |
31 /// | std.ResetEvent.set()32 /// | StaticResetEvent.set()
32 /// | std.ResetEvent.set()33 /// | StaticResetEvent.set()
33 /// std.ResetEvent.reset() |34 /// StaticResetEvent.reset() |
34 /// std.ResetEvent.wait() | (missed the second .set() notification above)35 /// StaticResetEvent.wait() | (missed the second .set() notification above)
35 state: usize = UNSET,36 state: usize = UNSET,
3637
37 const UNSET = 0;38 const UNSET = 0;
38 const SET = 1;39 const SET = 1;
3940
40 /// the minimum alignment for the `*std.ResetEvent` created by wait*()41 /// the minimum alignment for the `*StaticResetEvent` created by wait*()
41 const event_align = std.math.max(@alignOf(std.ResetEvent), 2);42 const event_align = std.math.max(@alignOf(StaticResetEvent), 2);
4243
43 pub fn wait(self: *AutoResetEvent) void {44 pub fn wait(self: *AutoResetEvent) void {
44 self.waitFor(null) catch unreachable;45 self.waitFor(null) catch unreachable;
...@@ -49,12 +50,9 @@ pub const AutoResetEvent = struct {...@@ -49,12 +50,9 @@ pub const AutoResetEvent = struct {
49 }50 }
5051
51 fn waitFor(self: *AutoResetEvent, timeout: ?u64) error{TimedOut}!void {52 fn waitFor(self: *AutoResetEvent, timeout: ?u64) error{TimedOut}!void {
52 // lazily initialized std.ResetEvent53 // lazily initialized StaticResetEvent
53 var reset_event: std.ResetEvent align(event_align) = undefined;54 var reset_event: StaticResetEvent align(event_align) = undefined;
54 var has_reset_event = false;55 var has_reset_event = false;
55 defer if (has_reset_event) {
56 reset_event.deinit();
57 };
5856
59 var state = @atomicLoad(usize, &self.state, .SeqCst);57 var state = @atomicLoad(usize, &self.state, .SeqCst);
60 while (true) {58 while (true) {
...@@ -72,7 +70,7 @@ pub const AutoResetEvent = struct {...@@ -72,7 +70,7 @@ pub const AutoResetEvent = struct {
72 // lazily initialize the ResetEvent if it hasn't been already70 // lazily initialize the ResetEvent if it hasn't been already
73 if (!has_reset_event) {71 if (!has_reset_event) {
74 has_reset_event = true;72 has_reset_event = true;
75 reset_event = std.ResetEvent.init();73 reset_event = .{};
76 }74 }
7775
78 // Since the AutoResetEvent currently isnt set,76 // Since the AutoResetEvent currently isnt set,
...@@ -97,9 +95,10 @@ pub const AutoResetEvent = struct {...@@ -97,9 +95,10 @@ pub const AutoResetEvent = struct {
97 };95 };
9896
99 // wait with a timeout and return if signalled via set()97 // wait with a timeout and return if signalled via set()
100 if (reset_event.timedWait(timeout_ns)) |_| {98 switch (reset_event.timedWait(timeout_ns)) {
101 return;99 .event_set => return,
102 } else |timed_out| {}100 .timed_out => {},
101 }
103102
104 // If we timed out, we need to transition the AutoResetEvent back to UNSET.103 // If we timed out, we need to transition the AutoResetEvent back to UNSET.
105 // If we don't, then when we return, a set() thread could observe a pointer to an invalid ResetEvent.104 // If we don't, then when we return, a set() thread could observe a pointer to an invalid ResetEvent.
...@@ -164,7 +163,7 @@ pub const AutoResetEvent = struct {...@@ -164,7 +163,7 @@ pub const AutoResetEvent = struct {
164 continue;163 continue;
165 }164 }
166165
167 const reset_event = @intToPtr(*align(event_align) std.ResetEvent, state);166 const reset_event = @intToPtr(*align(event_align) StaticResetEvent, state);
168 reset_event.set();167 reset_event.set();
169 return;168 return;
170 }169 }
lib/std/fs/test.zig+2-1
...@@ -758,7 +758,8 @@ test "open file with exclusive lock twice, make sure it waits" {...@@ -758,7 +758,8 @@ test "open file with exclusive lock twice, make sure it waits" {
758 }758 }
759 };759 };
760760
761 var evt = std.ResetEvent.init();761 var evt: std.ResetEvent = undefined;
762 try evt.init();
762 defer evt.deinit();763 defer evt.deinit();
763764
764 const t = try std.Thread.spawn(S.C{ .dir = &tmp.dir, .evt = &evt }, S.checkFn);765 const t = try std.Thread.spawn(S.C{ .dir = &tmp.dir, .evt = &evt }, S.checkFn);
lib/std/mutex.zig+9-8
...@@ -10,7 +10,7 @@ const assert = std.debug.assert;...@@ -10,7 +10,7 @@ const assert = std.debug.assert;
10const windows = os.windows;10const windows = os.windows;
11const testing = std.testing;11const testing = std.testing;
12const SpinLock = std.SpinLock;12const SpinLock = std.SpinLock;
13const ResetEvent = std.ResetEvent;13const StaticResetEvent = std.StaticResetEvent;
1414
15/// Lock may be held only once. If the same thread tries to acquire15/// Lock may be held only once. If the same thread tries to acquire
16/// the same mutex twice, it deadlocks. This type supports static16/// the same mutex twice, it deadlocks. This type supports static
...@@ -54,7 +54,7 @@ else if (builtin.link_libc or builtin.os.tag == .linux)...@@ -54,7 +54,7 @@ else if (builtin.link_libc or builtin.os.tag == .linux)
5454
55 const Node = struct {55 const Node = struct {
56 next: ?*Node,56 next: ?*Node,
57 event: ResetEvent,57 event: StaticResetEvent,
58 };58 };
5959
60 pub fn tryAcquire(self: *Mutex) ?Held {60 pub fn tryAcquire(self: *Mutex) ?Held {
...@@ -90,11 +90,12 @@ else if (builtin.link_libc or builtin.os.tag == .linux)...@@ -90,11 +90,12 @@ else if (builtin.link_libc or builtin.os.tag == .linux)
90 state = @atomicLoad(usize, &self.state, .Monotonic);90 state = @atomicLoad(usize, &self.state, .Monotonic);
91 }91 }
9292
93 // create the ResetEvent node on the stack93 // create the StaticResetEvent node on the stack
94 // (faster than threadlocal on platforms like OSX)94 // (faster than threadlocal on platforms like OSX)
95 var node: Node = undefined;95 var node: Node = .{
96 node.event = ResetEvent.init();96 .next = undefined,
97 defer node.event.deinit();97 .event = .{},
98 };
9899
99 // we've spun too long, try and add our node to the LIFO queue.100 // we've spun too long, try and add our node to the LIFO queue.
100 // if the mutex becomes available in the process, try and grab it instead.101 // if the mutex becomes available in the process, try and grab it instead.
...@@ -284,7 +285,7 @@ const WindowsMutex = struct {...@@ -284,7 +285,7 @@ const WindowsMutex = struct {
284 fn acquireSlow(self: *WindowsMutex) Held {285 fn acquireSlow(self: *WindowsMutex) Held {
285 // try to use NT keyed events for blocking, falling back to spinlock if unavailable286 // try to use NT keyed events for blocking, falling back to spinlock if unavailable
286 @setCold(true);287 @setCold(true);
287 const handle = ResetEvent.Impl.Futex.getEventHandle() orelse return self.acquireSpinning();288 const handle = StaticResetEvent.Impl.Futex.getEventHandle() orelse return self.acquireSpinning();
288 const key = @ptrCast(*const c_void, &self.state.waiters);289 const key = @ptrCast(*const c_void, &self.state.waiters);
289290
290 while (true) : (SpinLock.loopHint(1)) {291 while (true) : (SpinLock.loopHint(1)) {
...@@ -312,7 +313,7 @@ const WindowsMutex = struct {...@@ -312,7 +313,7 @@ const WindowsMutex = struct {
312 pub fn release(self: Held) void {313 pub fn release(self: Held) void {
313 // unlock without a rmw/cmpxchg instruction314 // unlock without a rmw/cmpxchg instruction
314 @atomicStore(u8, @ptrCast(*u8, &self.mutex.state.locked), 0, .Release);315 @atomicStore(u8, @ptrCast(*u8, &self.mutex.state.locked), 0, .Release);
315 const handle = ResetEvent.Impl.Futex.getEventHandle() orelse return;316 const handle = StaticResetEvent.Impl.Futex.getEventHandle() orelse return;
316 const key = @ptrCast(*const c_void, &self.mutex.state.waiters);317 const key = @ptrCast(*const c_void, &self.mutex.state.waiters);
317318
318 while (true) : (SpinLock.loopHint(1)) {319 while (true) : (SpinLock.loopHint(1)) {