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

Unmask async exceptions in STM transaction

我有一个函数,可以 post 向 STM 通道发出请求,然后阻止线程等待该请求完成。如果我的阻塞线程被异步异常终止,那么我想 post 向该 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 块之前,异步异常有可能会立即到达。如果发生这种情况,我会 post 编辑我的请求,但无法 post 取消它。

理想情况下,我想将第二行更改为

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

这样我就可以确保在我提交 requestPostSTM 事务后不会有异步异常潜入。但这当然不会编译,因为 restoreIO a -> IO a,而不是 STM a -> STM a

有什么方法可以仅在我的 STM 事务期间取消屏蔽异步异常?或者也许另一种方法可以保证异步异常到达并且我的第一个 STM 事务中止或者我的第一个 STM 事务提交并且没有异步异常可以终止我的线程,直到我使用 onException?[= 安装它的处理程序19=]

最好在屏蔽异步异常的情况下调用 requestPostSTM。所有重试的 STM 操作都是 interruptible, so they will be aborted in case of async exception, yet exception can't arrive in unexpected point. The rule is: if your action allocates resource (i.e. something, that should be deallocated), then you should run it with async exceptions masked, and rely on interruptible actions to abort the action at some known points (or pull async exceptions with allowInterrupt 手动操作)。