Allow Timeout to be constructed without specifying duration

This commit is contained in:
Mark Spanbroek 2020-11-11 11:36:19 +01:00 committed by markspanbroek
parent 930f599c73
commit e4a3a1d5e8
2 changed files with 25 additions and 21 deletions

View File

@ -2,30 +2,28 @@ import chronos
type Timeout* = ref object
timer: TimerCallback
callback: proc () {.gcsafe.}
onExpiry: proc () {.gcsafe.}
expired: AsyncEvent
proc setTimer(timeout: Timeout, duration: Duration) =
proc onTimeout(_: pointer) =
timeout.expired.fire()
timeout.callback()
timeout.onExpiry()
timeout.timer = setTimer(Moment.fromNow(duration), onTimeout)
const skip = proc () = discard
proc newTimeout*(duration: Duration, callback: proc {.gcsafe.} = skip): Timeout =
new result
result.expired = newAsyncEvent()
result.callback = callback
result.setTimer(duration)
proc newTimeout*(onExpiry: proc {.gcsafe.} = skip): Timeout =
Timeout(onExpiry: onExpiry, expired: newAsyncEvent())
proc reset*(timeout: Timeout, duration: Duration) =
timeout.timer.clearTimer()
proc stop*(timeout: Timeout) =
if not timeout.timer.isNil:
timeout.timer.clearTimer()
proc set*(timeout: Timeout, duration: Duration) =
timeout.stop()
timeout.expired.clear()
timeout.setTimer(duration)
proc stop*(timeout: Timeout) =
timeout.timer.clearTimer()
proc expired*(timeout: Timeout) {.async.} =
await timeout.expired.wait()

View File

@ -16,28 +16,32 @@ suite "timeout":
asynctest "can expire":
let duration = measure:
let timeout = newTimeout(10.milliseconds)
let timeout = newTimeout()
timeout.set(10.milliseconds)
await timeout.expired()
checkDuration duration, 10.milliseconds
asynctest "can be reset before expiry":
let duration = measure:
let timeout = newTimeout(10.milliseconds)
let timeout = newTimeout()
timeout.set(10.milliseconds)
await sleepAsync(5.milliseconds)
timeout.reset(10.milliseconds)
timeout.set(10.milliseconds)
await timeout.expired()
checkDuration duration, 15.milliseconds
asynctest "can be reset after expiry":
let duration = measure:
let timeout = newTimeout(10.milliseconds)
let timeout = newTimeout()
timeout.set(10.milliseconds)
await timeout.expired()
timeout.reset(10.milliseconds)
timeout.set(10.milliseconds)
await timeout.expired()
checkDuration duration, 20.milliseconds
asynctest "can be stopped":
let timeout = newTimeout(10.milliseconds)
let timeout = newTimeout()
timeout.set(10.milliseconds)
let expiry = timeout.expired()
await sleepAsync(5.milliseconds)
timeout.stop()
@ -48,7 +52,8 @@ suite "timeout":
asynctest "calls callback after expiry":
var called = false
proc callback = called = true
let timeout = newTimeout(10.milliseconds, callback)
let timeout = newTimeout(callback)
timeout.set(10.milliseconds)
await sleepAsync(5.milliseconds)
check not called
await sleepAsync(5.milliseconds)
@ -58,8 +63,9 @@ suite "timeout":
asynctest "calls callback multiple times":
var count = 0
proc callback = inc count
let timeout = newTimeout(10.milliseconds, callback)
let timeout = newTimeout(callback)
timeout.set(10.milliseconds)
await timeout.expired()
timeout.reset(10.milliseconds)
timeout.set(10.milliseconds)
await timeout.expired()
check count == 2