0

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?

amindfv
  • 8,438
  • 5
  • 36
  • 58

1 Answers1

8

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
   ...
Community
  • 1
  • 1
Roman Cheplyaka
  • 37,738
  • 7
  • 72
  • 121