module Main where

import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.QSem
import Data.IORef

data Stack e = Stack { 
    mvar :: MVar [e],
    available :: QSem 
    }

initStack lst = do
    mvar <- newMVar lst
    sem <- newQSem (length lst)
    return (Stack mvar sem)

push stack elem = do
    lst <- takeMVar (mvar stack)
    putMVar (mvar stack) (elem:lst)
    signalQSem (available stack)

pop stack = do
    waitQSem (available stack)
    (top:rest) <- takeMVar (mvar stack)
    putMVar (mvar stack) rest
    return top

main = do
    stack <- initStack ["one","two"]
    forkIO $ push stack "foo"
    forkIO $ push stack "bar"
    mapM_ (\i -> do
        val <- pop stack
        putStrLn $ (show i) ++ ":" ++ val)
        [1..4]
