Без маскировки асинхронные исключения могут происходить где угодно. При mask
асинхронные исключения могут появляться только из прерываемых действий (которые обычно блокируют). При uninterruptibleMask
асинхронные исключения полностью отсутствуют. Также обратите внимание, что allowInterrupt
является только одним из прерываемых действий;есть еще тонна, например, takeMVar
. С помощью mask
, например, невозможно заблокировать MVar
, не открывая себя для исключений, но uninterruptibleMask
позволяет вам это сделать (хотя вы не должны).
uninterruptibleCancel
- этополезно, потому что cancel
ожидает завершения целевого потока. Это операция блокировки, поэтому, как это принято, она также прерываема. Таким образом, когда вы используете cancel
, вы открываете себя для получения неожиданных исключений, независимо от того, * * вы mask
или нет. Когда вы используете uninterruptibleCancel
, вы гарантированно не получите исключение на 100%. Вот и все. Помните, что исключения не являются локальными;даже если ничего в cancel
не критично, то если оставить его незащищенным, исключение может проникнуть во что-то, что
mask $ do
cancel something -- whoops, this can receive an exception, even though it's masked
someCleanup -- therefore this might not get called
против
mask $ do
uninterruptibleCancel something -- no exceptions
someCleanup -- so this will definitely happen (assuming the target thread ends)