Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why putStrLn end of line is out of thread lock?

When I use putStrLn txt from several threads in Haskell, it's possible to get the text intercalated with the end of lines, but if I use putStr $ txt ++ "\n" always works.

is it right? What am I doing something wrong?

Example 1:

thread 1: putStrLn "txt 1"
thread 2: putStrLn "txt 2"
thread 3: putStrLn "txt 3"
thread 4: putStrLn "txt 4"
thread 5: putStrLn "txt 5"

Example of output:

txt 1txt 3
txt 2txt 5txt 4

Example 2:

thread 1: putStr $ "txt 1" ++ "\n"
thread 2: putStr $ "txt 2" ++ "\n"
thread 3: putStr $ "txt 3" ++ "\n"
thread 4: putStr $ "txt 4" ++ "\n"
thread 5: putStr $ "txt 5" ++ "\n"

Always output one line for thread:

txt 1
txt 3
txt 2
txt 5
txt 4

Thanks

Update: I'm using ghc 6.12.3 and base-4.2.0.2

like image 893
Zhen Avatar asked Jul 06 '11 16:07

Zhen


2 Answers

As far as I can tell, Haskell doesn't provide any thread safety guarantees on putStr, putStrLn and friends, so it would also be allowed to interleave character-by-character, even when doing the concatenation up front like you do.

See Can I ensure that Haskell performs atomic IO? for an example of how to synchronize your I/O properly.

like image 110
hammar Avatar answered Sep 28 '22 03:09

hammar


With the definition from base 4.3.0.0 (putStrLn s = do putStr s; putChar '\n' - thanks hammar) I would assume that putStr locks the stdout handle and is therefore able to output the string without intercalation. That would explain why the output intercalates when using putStrLn: the lock is released after putStr and another thread acquires the lock before putChar. I'm only speculating, though.

In any case, updating GHC and with it the base library to 4.3.1.0 should fix the problem.

like image 35
Antti Avatar answered Sep 28 '22 01:09

Antti