diff options
-rw-r--r-- | lib/pure/asyncdispatch.nim | 12 | ||||
-rw-r--r-- | tests/async/t12221.nim | 52 |
2 files changed, 61 insertions, 3 deletions
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 7c1b701b8..f4dc3de39 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -210,7 +210,12 @@ proc processPendingCallbacks(p: PDispatcherBase; didSomeWork: var bool) = cb() didSomeWork = true -proc adjustTimeout(pollTimeout: int, nextTimer: Option[int]): int {.inline.} = +proc adjustTimeout( + p: PDispatcherBase, pollTimeout: int, nextTimer: Option[int] +): int {.inline.} = + if p.callbacks.len != 0: + return 0 + if nextTimer.isNone() or pollTimeout == -1: return pollTimeout @@ -324,7 +329,7 @@ when defined(windows) or defined(nimdoc): result = false let nextTimer = processTimers(p, result) - let at = adjustTimeout(timeout, nextTimer) + let at = adjustTimeout(p, timeout, nextTimer) var llTimeout = if at == -1: winlean.INFINITE else: at.int32 @@ -1284,7 +1289,8 @@ else: result = false var keys: array[64, ReadyKey] let nextTimer = processTimers(p, result) - var count = p.selector.selectInto(adjustTimeout(timeout, nextTimer), keys) + var count = + p.selector.selectInto(adjustTimeout(p, timeout, nextTimer), keys) for i in 0..<count: let fd = keys[i].fd.AsyncFD let events = keys[i].events diff --git a/tests/async/t12221.nim b/tests/async/t12221.nim new file mode 100644 index 000000000..a6ccfb060 --- /dev/null +++ b/tests/async/t12221.nim @@ -0,0 +1,52 @@ +import asyncdispatch, os, times + +proc doubleSleep(hardSleep: int) {.async.} = + await sleepAsync(100) + sleep(hardSleep) + +template assertTime(target, timeTook: float): untyped {.dirty.} = + assert(timeTook*1000 > target - 1000, "Took too short, should've taken " & + $target & "ms, but took " & $(timeTook*1000) & "ms") + assert(timeTook*1000 < target + 1000, "Took too long, should've taken " & + $target & "ms, but took " & $(timeTook*1000) & "ms") + +var + start: float + fut: Future[void] + +# NOTE: this uses poll(3000) to limit timing error potential. +start = epochTime() +fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(40) +while not fut.finished: + poll(3000) +assertTime(150, epochTime() - start) + +start = epochTime() +fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(100) +while not fut.finished: + poll(3000) +assertTime(200, epochTime() - start) + +start = epochTime() +fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(40) and sleepAsync(300) +while not fut.finished: + poll(3000) +assertTime(300, epochTime() - start) + +start = epochTime() +fut = sleepAsync(50) and sleepAsync(150) and doubleSleep(100) and sleepAsync(300) +while not fut.finished: + poll(3000) +assertTime(300, epochTime() - start) + +start = epochTime() +fut = (sleepAsync(50) and sleepAsync(150) and doubleSleep(40)) or sleepAsync(700) +while not fut.finished: + poll(3000) +assertTime(150, epochTime() - start) + +start = epochTime() +fut = (sleepAsync(50) and sleepAsync(150) and doubleSleep(100)) or sleepAsync(700) +while not fut.finished: + poll(3000) +assertTime(200, epochTime() - start) |