Пожалуйста, не используйте unsafePerformIO с STM. STM имеет побочные эффекты под капотом, использование unsafePerformIO скрывает эти побочные эффекты, делая ваш код обманчиво нечистым и, следовательно, трудным или опасным для рефакторинга. Постарайся понять, поможет ли тебе параллельный пакет.
Одним из примеров небезопасных операций STM, являющихся небезопасными, является случай, когда вы используете «чистую» операцию STM, вложенную в другую (возможно, из библиотеки более высокого уровня). Например, приведенный ниже код повторяется (заканчивается <loop>
) из-за вложенных операций STM. Я помню, что старые версии GHC зависали, но сейчас не могу воспроизвести это поведение в GHC 7.0.1.
import Control.Concurrent
import Control.Concurrent.STM
import System.IO.Unsafe
import GHC.Conc.Sync
main = newTVarIO 5 >>= runComputation >>= print
runComputation :: TVar Int -> IO Int
runComputation tv = atomically $ do
let y = getFiveUnsafe tv + 1
writeTVar tv y
return y
getFiveUnsafe tv = unsafePerformIO . atomically $ do
x <- readTVar tv
writeTVar tv (x + 5)
return x
(я приветствую других людей, которые редактируют и добавляют более убедительные примеры - я считаю, что есть лучшие)