aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-05-04 15:16:39 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-05-04 15:16:39 -0400
commit09cbcf8841a0b80cdbdf40c2b48acccbaa945ce8 (patch)
treededa8f8f46e2033b1f6c3d19d8e2b52ae1fab9e6
parent70a9ee3dd68d8ed28a9fd2dc29f6c88fee5d789e (diff)
downloadzig-09cbcf8841a0b80cdbdf40c2b48acccbaa945ce8.tar.gz
zig-09cbcf8841a0b80cdbdf40c2b48acccbaa945ce8.zip
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.
-rw-r--r--std/os/time.zig33
1 files changed, 12 insertions, 21 deletions
diff --git a/std/os/time.zig b/std/os/time.zig
index 99c8b59927..abb6412843 100644
--- a/std/os/time.zig
+++ b/std/os/time.zig
@@ -13,44 +13,35 @@ const posix = std.os.posix;
pub const epoch = @import("epoch.zig");
-/// Sleep for the specified duration
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
pub fn sleep(nanoseconds: u64) void {
switch (builtin.os) {
Os.linux, Os.macosx, Os.ios, Os.freebsd, Os.netbsd => {
const s = nanoseconds / ns_per_s;
const ns = nanoseconds % ns_per_s;
- posixSleep(@intCast(u63, s), @intCast(u63, ns));
+ posixSleep(s, ns);
},
Os.windows => {
const ns_per_ms = ns_per_s / ms_per_s;
const milliseconds = nanoseconds / ns_per_ms;
- windows.Sleep(@intCast(windows.DWORD, milliseconds));
+ const ms_that_will_fit = std.math.cast(windows.DWORD, milliseconds) catch std.math.maxInt(windows.DWORD);
+ windows.Sleep(ms_that_will_fit);
},
else => @compileError("Unsupported OS"),
}
}
-pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
- var req: posix.timespec = undefined;
+/// Spurious wakeups are possible and no precision of timing is guaranteed.
+pub fn posixSleep(seconds: u64, nanoseconds: u64) void {
+ var req = posix.timespec{
+ .tv_sec = std.math.cast(isize, seconds) catch std.math.maxInt(isize),
+ .tv_nsec = std.math.cast(isize, nanoseconds) catch std.math.maxInt(isize),
+ };
var rem: posix.timespec = undefined;
-
- var req_sec = seconds;
- var req_nsec = nanoseconds;
-
while (true) {
- req.tv_sec = math.min(math.maxInt(isize), req_sec);
- req.tv_nsec = @intCast(isize, req_nsec);
-
- req_sec -= @intCast(u63, req.tv_sec);
- req_nsec = 0;
-
const ret_val = posix.nanosleep(&req, &rem);
const err = posix.getErrno(ret_val);
switch (err) {
- 0 => {
- // If there's still time to wait keep running the loop
- if (req_sec == 0 and req_nsec == 0) return;
- },
posix.EFAULT => unreachable,
posix.EINVAL => {
// Sometimes Darwin returns EINVAL for no reason.
@@ -58,10 +49,10 @@ pub fn posixSleep(seconds: u63, nanoseconds: u63) void {
return;
},
posix.EINTR => {
- req_sec += @intCast(u63, rem.tv_sec);
- req_nsec = @intCast(u63, rem.tv_nsec);
+ req = rem;
continue;
},
+ // This prong handles success as well as unexpected errors.
else => return,
}
}