Reputation: 8448
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 IORef
s wrong, but not noticing because ghci isn't truly multithreaded?
Upvotes: 0
Views: 315
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