Ниже приведен исходный код примера программы:
Когда я запускаю его из ghci, и printJob, и printJob2 работают нормально и записывают десять строк в текстовый файл.
Но при компиляции с флагом -threaded программа записывает только одну строку.
У меня есть ghc 7.0.3 на ArchLinux.
Вот команда компиляции:
ghc -threaded -Wall -O2 -rtsopts -with-rtsopts=-N -o testmvar testmvar.hs
Что я делаю неправильно? Почему он не работает в потоковом режиме?
import Control.Concurrent.MVar
import Control.Concurrent (forkIO)
import Control.Exception (bracket)
import Control.Monad (forM_)
import System.IO.Unsafe (unsafePerformIO)
import System.IO (hPutStrLn, stderr)
{-# NOINLINE p #-}
p :: MVar Int
p = unsafePerformIO $ newMVar (1::Int)
{-# NOINLINE printJob #-}
printJob x = bracket (takeMVar p) (putMVar p . (+ 1))
(\a -> do
appendFile "mvarlog.txt" $ "Input: " ++ x ++ "; Counter: " ++ show a ++ "\n"
)
{-# NOINLINE printJob2 #-}
printJob2 = unsafePerformIO $ do
p2 <- newEmptyMVar
return $ (\x -> bracket (putMVar p2 True) (\_ -> takeMVar p2)
(\_ -> do
appendFile "mvarlog.txt" $ "preformed " ++ x ++ "\n"
))
main = do
forM_ [1..10]
(\x -> forkIO $ printJob (show x))
РЕДАКТИРОВАТЬ: Хаммар указал, что если основное приложение завершается раньше, чем все порожденные потоки, то они будут убиты, и предложил добавить задержку в конце основного. Я так и сделал, как он и предсказывал, это работает.
unsafePerformIO
), но я чувствую, что стоит еще раз сказать, чтоunsafePerformIO
есть, как имя означает, небезопасно, и что-то сломается, если вы его используете. (Хорошо, если вы не очень, очень осторожны, но, возможно, и в этом случае тоже.) - person Antal Spector-Zabusky   schedule 26.02.2012main
? Все остальные потоки уничтожаются после завершения основного потока, поэтому в зависимости от того, как запланированы дела, это может ничего не делать — независимо от каких-либо проблем, связанных сunsafePerformIO
. - person hammar   schedule 26.02.2012MVar
с помощьюunsafePerformIO
. - person danr   schedule 28.02.2012