[Haskell-cafe] synchronous channels in STM

Arnar Birgisson arnarbi at gmail.com
Thu Oct 9 12:10:18 EDT 2008


Hi there,

2008/10/9 David Leimbach <leimy2k at gmail.com>:
> see writeTChan and readTChan.  I assume readTChan is synchronous :-).
>  writeTChan may be asynchronous for all I can tell (haven't looked deeply).

writeTChan is asynchronous, i.e. channels in this case are unbounded buffers.

> But I did write a concurrent prime sieve with it:

I did the same, with the one-place-buffers (the MVars implemented over
STM). Be warned that there is no stop condition, this just keeps
printing primes forever.

import Control.Concurrent (forkIO)
import Control.Concurrent.STM

-- MVars from the STM paper
type MVar a = TVar (Maybe a)

newEmptyMVar :: STM (MVar a)
newEmptyMVar = newTVar Nothing

takeMVar :: MVar a -> STM a
takeMVar mv
 = do v <- readTVar mv
      case v of
        Nothing  -> retry
        Just val -> do writeTVar mv Nothing
                       return val

putMVar :: MVar a -> a -> STM ()
putMVar mv val
 = do v <- readTVar mv
      case v of
        Nothing  -> writeTVar mv (Just val)
        Just _   -> retry

-- Sieve
forever a = do a; forever a

pfilter :: Int -> MVar Int -> MVar Int -> IO ()
pfilter p in_ out =
    forever $ do atomically $ do v <- takeMVar in_
                                 if v `mod` p /= 0
                                    then putMVar out v
                                    else return ()

sieve :: MVar Int -> MVar Int -> IO ()
sieve in_ out =
    do p <- atomically $ takeMVar in_
       atomically $ putMVar out p
       ch <- atomically $ newEmptyMVar
       forkIO $ pfilter p in_ ch
       sieve ch out

feeder :: MVar Int -> IO ()
feeder out = feed' 2
           where
             feed' i = do atomically $ putMVar out i
                          feed' (i+1)

printer :: MVar Int -> IO ()
printer in_ = forever $ do v <- atomically $ takeMVar in_
                           putStrLn $ show v

main :: IO ()
main = do in_ <- atomically newEmptyMVar
          out <- atomically newEmptyMVar
          forkIO $ feeder in_
          forkIO $ printer out
          forkIO $ sieve in_ out
          return ()


cheers,
Arnar


More information about the Haskell-Cafe mailing list