authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-04 15:16:39-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-04 15:16:39-04:00
log09cbcf8841a0b80cdbdf40c2b48acccbaa945ce8
treededa8f8f46e2033b1f6c3d19d8e2b52ae1fab9e6
parent70a9ee3dd68d8ed28a9fd2dc29f6c88fee5d789e
signature Commit is signed but in an unrecognized format.

std lib sleep APIs: add doc comments and no @intCast

The sleep APIs are now documented as having spurious wakeups and no precision of timing guaranteed. They also cannot fail. This commit makes the entire range of u64 legal values to pass to std.os.time.sleep and std.os.time.posixSleep. Values that do not fit in the native system APIs will cause a sleep for the longest possible duration and then be handled as a spurious wakeup.

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

std/os/time.zig+12-21
......@@ -13,44 +13,35 @@ const posix = std.os.posix;
1313
1414pub const epoch = @import("epoch.zig");
1515
16/// Sleep for the specified duration
16/// Spurious wakeups are possible and no precision of timing is guaranteed.
1717pub fn sleep(nanoseconds: u64) void {
1818 switch (builtin.os) {
1919 Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
2020 const s = nanoseconds / ns_per_s;
2121 const ns = nanoseconds % ns_per_s;
22 posixSleep(@intCast(u63, s), @intCast(u63, ns));
22 posixSleep(s, ns);
2323 },
2424 Os.windows => {
2525 const ns_per_ms = ns_per_s / ms_per_s;
2626 const milliseconds = nanoseconds / ns_per_ms;
27 windows.Sleep(@intCast(windows.DWORD, milliseconds));
27 const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
28 windows.Sleep(ms_that_will_fit);
2829 },
2930 else => @compileError("Unsupported OS"),
3031 }
3132}
3233
33pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
34 var req: posix.timespec = undefined;
34/// Spurious wakeups are possible and no precision of timing is guaranteed.
35pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
36 var req = posix.timespec{
37 .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
38 .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
39 };
3540 var rem: posix.timespec = undefined;
36
37 var req_sec = seconds;
38 var req_nsec = nanoseconds;
39
4041 while (true) {
41 req.tv_sec = math.min(math.maxInt(isize), req_sec);
42 req.tv_nsec = @intCast(isize, req_nsec);
43
44 req_sec -= @intCast(u63, req.tv_sec);
45 req_nsec = 0;
46
4742 const ret_val = posix.nanosleep(&req, &rem);
4843 const err = posix.getErrno(ret_val);
4944 switch (err) {
50 0 => {
51 // If there's still time to wait keep running the loop
52 if (req_sec == 0 and req_nsec == 0) return;
53 },
5445 posix.EFAULT => unreachable,
5546 posix.EINVAL => {
5647 // Sometimes Darwin returns EINVAL for no reason.
......@@ -58,10 +49,10 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
5849 return;
5950 },
6051 posix.EINTR => {
61 req_sec += @intCast(u63, rem.tv_sec);
62 req_nsec = @intCast(u63, rem.tv_nsec);
52 req = rem;
6353 continue;
6454 },
55 // This prong handles success as well as unexpected errors.
6556 else => return,
6657 }
6758 }