在STM事务中取消屏蔽异步异常

我有一个函数向STM通道发送请求,然后阻塞等待请求完成的线程。 如果我的阻塞线程被异步异常终止,那么我想发送取消请求到该STM通道。 它目前看起来像这样:

runRequest channel request = mask $ restore -> do
  (reqId, resultVar) <- restore . atomically $ requestPostSTM channel request
  onException
    (restore . atomically $ do
      maybeResult <- readTVar resultVar
      case maybeResult of
        Just x -> return x
        Nothing -> retry)
    (atomically $ requestCancelSTM channel reqId)

这几乎是我所需要的,但异常异常在requestPostSTM事务成功后才会到达,但仍然在我们退出restore块之前有一点小可能性。 如果发生这种情况,那么我会发布我的请求,但无法发布取消消息。

理想情况下,我想将第二行更改为类似的内容

  (reqId, resultVar) <- atomically . restore $ requestPostSTM channel request

通过这种方式,我确信在requestPostSTM事务提交之后,没有任何异步异常可以潜入。 但是,这当然不会编译,因为restoreIO a -> IO a ,而不是STM a -> STM a

有没有什么办法可以在我的STM事务持续时间内揭露异步异常? 或者也许另一种方式来保证异步异常到达,我的第一个STM事务异常终止或我的第一个STM事务提交并且没有异步异常可以终止我的线程,直到我用onException安装它的处理程序?


最好调用requestPostSTM并屏蔽异步异常。 所有重试的STM操作都是可中断的,所以它们将在异步异常情况下中止,但异常无法到达意外的地方。 规则是:如果你的动作分配了资源(即某些东西应该被释放),那么你应该在屏蔽异步异常的情况下运行它,并且依靠可中断的动作来中止某些已知点的动作(或者用allowInterrupt手动allowInterrupt异步异常)。

链接地址: http://www.djcxy.com/p/81465.html

上一篇: Unmask async exceptions in STM transaction

下一篇: What is the precise reason I got blocked on STM?