我有一個函數將請求發送到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
交易COMMITED後沒有異步異常可能會偷偷英寸但是,這當然不會編譯,因爲restore
是IO a -> IO a
,而不是STM a -> STM a
。
有沒有什麼辦法可以解除異步異常,僅用於我的STM事務?或者,也許另一種方式來保證異步異常到達,我的第一個STM事務中止或我的第一個STM事務提交,並且沒有異步異常可以終止我的線程,直到我爲它安裝處理程序onException
?
爲什麼你想在這裏恢復異步異常?如果'requestPostSTM'分配資源,那麼它應該被屏蔽異步異常執行。請注意'原子'是可中斷的。 – Yuras
'''requestPostSTM'''在內部寫入一個有界的chan並可能重試。也許這只是我的完美主義,但允許異步異常終止該事務似乎是合法的。 – Anton
即使異步異常被屏蔽,那麼'STM'操作即重試將異步異常中止(如果有的話),請參閱https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Exception .html#g:13 – Yuras