I have the following code which run the passed proc in an interval, and return a clearInterval proc to stop the run, as follow:
proc runInterval(cb: proc, interval: int): Future[proc()] {.async.} =
var stop_run = false
while not(stop_run):
await sleepAsync(intv)
cb()
proc clearInterval() =
stop_run = true
return clearInterval
proc in_interval() =
echo "hahah"
let clearInterval = runInterval(in_interval, 1000) # run the in_interval proc every 1 second
clearInterval() # stop in_interval
runForever()
I suspect type annotation of runInterval is not correct as
: Future[proc()] {.async.}
, but I dont know how can I define a proc which has a proc returnning type as well as {.async.} ?Maybe what you want is async with cancelation?
Chronos supports that, and mashingan gave an example for Nim async here:
I guess this is what you want.
import asyncdispatch
type
Action = proc(): void {.gcsafe.}
proc runInterval(cb: Action, interval: int): Future[Action] {.async.} =
var running = true
result = proc() =
running = false
proc loop() =
if running:
addTimer interval, true, proc(fd: AsyncFD): bool =
if running:
cb()
loop()
loop()
proc main() {.async.} =
var stop: Action
var called = 0
proc callback() {.gcsafe.} =
# stop after called three times
called.inc
echo "called=", called
if called >= 3:
echo "stopping "
stop()
# run the in_interval proc every 1 second
stop = await runInterval(callback, 1000)
when isMainModule:
asyncCheck main()
while hasPendingOperations():
poll()
Thanks for all the replies! It looks like the most elegant/simple way to "clear" an interval is to using chronos library,
import chronos
proc test() {.async.} =
while true:
await sleepAsync(1000)
echo "test"
proc run() {.async.} =
let fut = test()
await sleepAsync(4000)
fut.cancel()
waitFor(run())
and that's exactlly what I want: fire up number of jobs running in time interval, and cancel them unconditionally using the handler (fut). @jackhftang's solution works but I think chronos is easier / simpler.