Using TChan with Timeout

前端 未结 3 674
谎友^
谎友^ 2021-02-14 19:49

I have a TChan as input for a thread which should behave like this:

If sombody writes to the TChan within a specific time, the content should be retrieved. If there is n

3条回答
  •  面向向阳花
    2021-02-14 20:07

    The thumb rule of concurrency is: if adding a sleep in some point inside an IO action matters, your program is not safe.

    To understand why the code timeout 1000000 $ atomically $ readTChan pktChannel does not work, consider the following alternative implementation of atomically:

    atomically' :: STM a -> IO a
    atomically' action = do
      result <- atomically action
      threadDelay someTimeAmount
      return result
    

    The above is equal to atomically, but for an extra innocent delay. Now it is easy to see that if timeout kills the thread during the threadDelay, the atomic action has completed (consuming a message from the channel), yet timeout will return Nothing.

    A simple fix to timeout n $ atomically ... could be the following

    smartTimeout :: Int -> STM a -> IO (Maybe a)
    smartTimeout n action = do
       v <- atomically $ newEmptyTMvar
       _ <- timeout n $ atomically $ do
              result <- action
              putTMvar v result
       atomically $ tryTakeTMvar v
    

    The above uses an extra transactional variable v to do the trick. The result value of the action is stored into v inside the same atomic block in which the action is run. The return value of timeout is not trusted, since it does not tell us if action was run or not. After that, we check the TMVar v, which will be full if and only if action was run.

提交回复
热议问题