Предположим, что у меня есть код, написанный так:
import Control.Exception (bracketOnError, finally, mask)
import Client (acquireB, releaseB, doStuff) -- theoretical
import MyStuff (preliminary, doMoreStuff) -- theoretical
clientAction = bracketOnError acquireB releaseB $ \b ->
doStuff b
return (b, releaseB b)
myAction = mask $ \restore ->
a <- preliminary
(thing, releaseThing) <- restore clientAction
doMoreStuff a thing `finally` releaseThing
Мне нужно сделать некоторые вещи preliminary
, мой клиент приобретает b
, а затем должен doStuff
с b
, а затем я должен doMoreStuff
с b
. И b
должен быть выпущен, даже если возникает асинхронное исключение. Но я не знаю, как выпустить b
, поэтому мой клиент говорит мне, как это сделать. Написанный таким образом, мы оба готовы выпустить b
, если исключение происходит во время "нашего" кода.
Мой вопрос в следующем: возможно ли, когда исключение async вызывает releaseB
не выполняться? В частности, существует ли разрыв между "моим кодом" и "кодом моего клиента", в котором может сжиматься исключение async? Позвольте мне вставить clientAction
и bracketOnException
, чтобы объяснить.
myAction = mask $ \restore -> do
a <- preliminary
(thing, releaseThing) <- restore $ mask $ \restore2 -> do
b <- acquireB
restore2 (doStuff b >> return (b, releaseB b))
`onException` releaseB b
doMoreStuff a thing `finally` releaseThing
Конкуренция такова: есть ли здесь момент здесь
... restore $ mask ...
Правильно, когда клиент mask
снят, но до конца моего restore
, окружающего его, где исключение может прокрасться через?