次のコードがあります。
module Main where
import Data.IORef
import qualified Data.ByteString as S
import Control.Monad
import Control.Concurrent
main :: IO ()
main = do
var <- newIORef False
forkIO $ forever $ do
status <- readIORef var
if status
then putStrLn "main: file was read"
else putStrLn "main: file not yet read"
threadDelay 10000
threadDelay 200000
putStrLn ">>! going to read file"
--threadDelay 200000 --
str <- S.readFile "large2"
putStrLn ">>! finished reading file"
writeIORef var True
threadDelay 200000
コードをコンパイルして、次のように実行します。
$ ghc -threaded --make test.hs
$ dd if=/dev/urandom of=large bs=800000 count=1024
$ ./test +RTS -N3
<...>
main: file not yet read
main: file not yet read
main: file not yet read
main: file not yet read
>>! going to read file
>>! finished reading file
main: file was read
main: file was read
main: file was read
main: file was read
<...>
つまり、プログラムはファイルの読み取り中に一時停止します。readFile
これを置き換えるとthreadDelay
コントロールが正しく生成されるため、これはわかりにくいと思います。
ここで何が起こっているのですか?GHCforkIO
は別のシステム スレッドにコードをマッピングしていませんか?
(私は Mac OS X 10.8.5 を使用していますが、Ubuntu と Debian で同じ動作が報告されています)