time: use `Duration(C.INT64_MAX)` as infinite (#10539)

pull/10495/head
Uwe Krüger 2021-06-22 11:17:44 +02:00 committed by GitHub
parent dd6591b2f5
commit 72358833e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 49 additions and 24 deletions

View File

@ -14,7 +14,7 @@ pub const no_timeout = time.Duration(0)
// infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions
// only ever return with data)
pub const infinite_timeout = time.Duration(-1)
pub const infinite_timeout = time.infinite
// Shutdown shutsdown a socket and closes it
fn shutdown(handle int) ? {
@ -34,7 +34,7 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
C.FD_ZERO(&set)
C.FD_SET(handle, &set)
seconds := timeout.milliseconds() / 1000
seconds := timeout / time.second
microseconds := time.Duration(timeout - (seconds * time.second)).microseconds()
mut tt := C.timeval{
@ -93,9 +93,8 @@ fn select_with_retry(handle int, test Select, timeout time.Duration) ?bool {
// wait_for_common wraps the common wait code
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
if deadline.unix == 0 {
// only accept infinite_timeout as a valid
// negative timeout - it is handled in @select however
if timeout < 0 && timeout != net.infinite_timeout {
// do not accept negative timeout
if timeout < 0 {
return err_timed_out
}
ready := select_with_retry(handle, test, timeout) ?

View File

@ -29,8 +29,8 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
C.FD_ZERO(&set)
C.FD_SET(handle, &set)
seconds := timeout.milliseconds() / 1000
microseconds := timeout - (seconds * time.second)
seconds := timeout / time.second
microseconds := time.Duration(timeout - (seconds * time.second)).microseconds()
mut tt := C.timeval{
tv_sec: u64(seconds)
@ -63,9 +63,8 @@ fn @select(handle int, test Select, timeout time.Duration) ?bool {
// wait_for_common wraps the common wait code
fn wait_for_common(handle int, deadline time.Time, timeout time.Duration, test Select) ? {
if deadline.unix == 0 {
// only accept infinite_timeout as a valid
// negative timeout - it is handled in @select however
if timeout < 0 && timeout != unix.infinite_timeout {
// do not accept negative timeout
if timeout < 0 {
return net.err_timed_out
}
ready := @select(handle, test, timeout) ?
@ -117,7 +116,7 @@ const (
// infinite_timeout should be given to functions when an infinite_timeout is wanted (i.e. functions
// only ever return with data)
const (
infinite_timeout = time.Duration(-1)
infinite_timeout = time.infinite
)
[inline]

View File

@ -107,10 +107,7 @@ fn (mut en EpollNotifier) wait(timeout time.Duration) []FdEvent {
// the added bonus of making EpollNotifier thread safe
events := [512]C.epoll_event{}
// populate events with the new events
to := match timeout {
time.infinite { -1 }
else { int(timeout / time.millisecond) }
}
to := timeout.sys_milliseconds()
count := C.epoll_wait(en.epoll_fd, &events[0], events.len, to)
if count > 0 {

View File

@ -8,6 +8,8 @@
module sync
import time
fn do_rec_i64(mut ch Channel) {
mut sum := i64(0)
for _ in 0 .. 300 {
@ -56,7 +58,7 @@ fn test_select() {
mut sl := i64(0)
mut objs := [voidptr(&ri), &sl, &rl, &rb]
for _ in 0 .. 1200 {
idx := channel_select(mut channels, directions, mut objs, -1)
idx := channel_select(mut channels, directions, mut objs, time.infinite)
match idx {
0 {
sum += ri

View File

@ -602,8 +602,8 @@ fn (mut ch Channel) try_pop_priv(dest voidptr, no_block bool) ChanState {
}
// Wait `timeout` on any of `channels[i]` until one of them can push (`is_push[i] = true`) or pop (`is_push[i] = false`)
// object referenced by `objrefs[i]`. `timeout < 0` means wait unlimited time. `timeout == 0` means return immediately
// if no transaction can be performed without waiting.
// object referenced by `objrefs[i]`. `timeout = time.infinite` means wait unlimited time. `timeout <= 0` means return
// immediately if no transaction can be performed without waiting.
// return value: the index of the channel on which a transaction has taken place
// -1 if waiting for a transaction has exceeded timeout
// -2 if all channels are closed
@ -646,7 +646,11 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
C.atomic_store_u16(&ch.read_sub_mtx, u16(0))
}
}
stopwatch := if timeout <= 0 { time.StopWatch{} } else { time.new_stopwatch({}) }
stopwatch := if timeout == time.infinite || timeout <= 0 {
time.StopWatch{}
} else {
time.new_stopwatch({})
}
mut event_idx := -1 // negative index means `timed out`
outer: for {
@ -679,10 +683,10 @@ pub fn channel_select(mut channels []&Channel, dir []Direction, mut objrefs []vo
event_idx = -2
break outer
}
if timeout == 0 {
if timeout <= 0 {
break outer
}
if timeout > 0 {
if timeout != time.infinite {
remaining := timeout - stopwatch.elapsed()
if !sem.timed_wait(remaining) {
break outer

View File

@ -176,7 +176,7 @@ pub fn (mut sem Semaphore) timed_wait(timeout time.Duration) bool {
C.GetSystemTimeAsFileTime(&ft_start)
time_end := ((u64(ft_start.dwHighDateTime) << 32) | ft_start.dwLowDateTime) +
u64(timeout / (100 * time.nanosecond))
mut t_ms := u32(timeout / time.millisecond)
mut t_ms := timeout.sys_milliseconds()
C.AcquireSRWLockExclusive(&sem.mtx)
mut res := 0
c = C.atomic_load_u32(&sem.count)

View File

@ -394,7 +394,7 @@ pub const (
second = Duration(1000 * millisecond)
minute = Duration(60 * second)
hour = Duration(60 * minute)
infinite = Duration(-1)
infinite = Duration(C.INT64_MAX)
)
// nanoseconds returns the duration as an integer number of nanoseconds.

View File

@ -149,3 +149,15 @@ pub fn sleep(duration Duration) {
}
}
}
// some *nix system functions (e.g. `C.poll()`, C.epoll_wait()) accept an `int`
// value as *timeout in milliseconds* with the special value `-1` meaning "infinite"
pub fn (d Duration) sys_milliseconds() int {
if d > C.INT32_MAX * millisecond { // treat 2147483647000001 .. C.INT64_MAX as "infinite"
return -1
} else if d <= 0 {
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
} else {
return int(d / millisecond)
}
}

View File

@ -225,3 +225,15 @@ pub fn wait(duration Duration) {
pub fn sleep(duration Duration) {
C.Sleep(int(duration / millisecond))
}
// some Windows system functions (e.g. `C.WaitForSingleObject()`) accept an `u32`
// value as *timeout in milliseconds* with the special value `u32(-1)` meaning "infinite"
pub fn (d Duration) sys_milliseconds() u32 {
if d >= u32(-1) * millisecond { // treat 4294967295000000 .. C.INT64_MAX as "infinite"
return u32(-1)
} else if d <= 0 {
return 0 // treat negative timeouts as 0 - consistent with Unix behaviour
} else {
return u32(d / millisecond)
}
}

View File

@ -4102,7 +4102,7 @@ fn (mut g Gen) select_expr(node ast.SelectExpr) {
} else if has_else {
g.write('0')
} else {
g.write('-1')
g.write('_const_time__infinite')
}
g.writeln(');')
// free the temps that were created