with the interest of cancellation in async , i scratched a simple implentation, 
just a rewrite of `asyncdispatch.waitFor`. then i encountered some problem:

  1. why the `poll()` will `raise exception("An attempt was made to complete a 
Future more than once.")`
  2. why the future is still running after called it's `.fail`?`



for the first problem, i found and read this 
[issue](https://github.com/nim-lang/Nim/issues/14564); as i could not 
understand how `addTimer` can rescue it, i just ignored this specific exception 
... (i tried to add `addTimer` but it's a shame i didn't know how)

for the second problem, i tried to add a `break` in the `try: poll..catch` 
block, the output did change, but "the future is still running after called 
`.fail`" remains.

thanks for help.
    
    
    import std/[asyncdispatch, times, asyncfutures]
    import std/[strutils, strformat]
    
    type Canceled = object of CatchableError
    
    proc ticker(ident, stop, interval: int) {.async.} =
      var remain = stop
      while remain > 0:
        echo &"tick#{ident}: ", now()
        dec remain
        await sleepAsync(interval)
      
      echo &"tick#{ident}: exiting"
    
    
    proc waitFor[T](timeout: int, fut: Future[T]): T =
      let deadline = epochTime() + timeout.float
      var timedOut = true
      
      while epochTime() < deadline:
        if fut.finished:
          timedOut = false
          break
        
        try:
          poll()
        except:
          let e = getCurrentException()
          if not e.msg.startsWith("An attempt was made to complete a Future 
more than once."):
            raise e
          # break
      
      if timedOut:
        fut.fail newException(Canceled, "canceled due to deadline")
      
      fut.read
    
    proc main: int =
      try:
        1.waitFor ticker(1, 3, 500)
      except Canceled:
        let err = getCurrentException()
        echo "ticker has been canceled ", err.msg
      
      5.waitFor ticker(2, 3, 500)
    
    when isMainModule:
      quit main()
    
    
    Run

output:
    
    
    tick#1: 2022-02-12T17:05:21+08:00
    tick#1: 2022-02-12T17:05:21+08:00
    tick#1: 2022-02-12T17:05:22+08:00
    ticker has been canceled canceled due to deadline
    Async traceback:
    Exception message: canceled due to deadline
    
    tick#2: 2022-02-12T17:05:22+08:00
    tick#1: exiting
    tick#2: 2022-02-12T17:05:22+08:00
    tick#2: 2022-02-12T17:05:23+08:00
    tick#2: exiting
    
    
    Run

Reply via email to