amindfv
amindfv

Reputation: 8448

Different concurrency behavior in ghci and runghc

I have some simple code which prints to the screen at fixed intervals of time, unless an IORef is set to indicate that the user is currently typing:

import Data.IORef
import Control.Concurrent

main = do
   amTyping <- newIORef False
   forkIO $ printALot amTyping
   aChar <- getChar
   writeIORef amTyping True
   aLine <- getLine
   writeIORef amTyping False
   putStrLn $ aChar : aLine
   main

printALot :: IORef Bool -> IO ()
printALot theRef = do
   putStrLn "1111111"
   threadDelay 1000000
   isTyping <- readIORef theRef
   if isTyping
      then return ()
      else printALot theRef

This works beautifully in GHCi, but when I use it with runghc (or compile it), the read of or write to the IORef seems not to work -- printALot just continues looping, overrunning anything the user types.

What's the difference here between ghci and runghc/compiled? Am I using IORefs wrong, but not noticing because ghci isn't truly multithreaded?

Upvotes: 0

Views: 315

Answers (1)

Roman Cheplyaka
Roman Cheplyaka

Reputation: 38708

This has nothing to do with concurrency.

Your interpreted and compiled programs differ in the terminal mode they use: non-canonical vs canonical.

In the canonical mode, your program doesn't get the character before the whole line is available — hence the effect you are observing.

To fix this, simply put the handle in the non-buffering mode:

import System.IO

main = do
   hSetBuffering stdin NoBuffering
   ...

Upvotes: 8

Related Questions