[Haskell-cafe] Is it safe to create global variables using unsafePerformIO?

Alexander Alexeev mail at eax.me
Wed Jan 29 07:32:26 UTC 2014


Lets consider the following code:

import Control.Concurrent
import Control.Concurrent.STM
import System.IO.Unsafe (unsafePerformIO)

{-# NOINLINE counter #-}
counter :: TVar Int
counter = unsafePerformIO $ newTVarIO 0

incCounter :: IO Int
incCounter = do
  r <- atomically $ do
    t <- readTVar counter
    let t' = t + 1
    writeTVar counter t'
    return t'
  return r

main :: IO ()
main = do
  n1 <- incCounter
  print n1
  n2 <- incCounter
  print n2
  n3 <- incCounter
  print n3

This program prints:


So we have a "global variable". Do I right understand that newTVarIO
creates TVar and RTS memoizes it since 'counter' function is pure? If
it's true, could it happen that under some circumstances memoized value
will be deleted from memory? Or Haskell keeps all memoized values

Another issue which I'm afraid of --- would the given code be safe in
multithread application? For example, is it possible to encounter a
race condition if two threads will try to create a new counter in the
same time?

Is there any other problems which should be taken in account?

Best regards,
Alexander Alexeev

More information about the Haskell-Cafe mailing list