module Data.IVar.Simple (
IVar,
new,
newFull,
read,
tryRead,
write,
tryWrite,
BlockedIndefinitelyOnIVar,
) where
import Control.Concurrent.MVar
import Control.Exception
import Control.Monad
import Data.Typeable
import System.IO.Unsafe
import Prelude hiding (read)
data IVar a = IVar (MVar ()) (MVar a) a
new :: IO (IVar a)
new = do
lock <- newMVar ()
trans <- newEmptyMVar
let
value = unsafePerformIO $ takeMVar trans
return (IVar lock trans value)
newFull :: a -> IO (IVar a)
newFull value = do
lock <- newEmptyMVar
return (IVar lock (error "unused MVar") value)
read :: IVar a -> a
read (IVar _ _ value) = value
tryRead :: IVar a -> IO (Maybe a)
tryRead (IVar lock _ value) = do
empty <- isEmptyMVar lock
if empty then return (Just value) else return Nothing
write :: IVar a -> a -> IO ()
write ivar value = do
result <- tryWrite ivar value
when (not result) $ throwIO BlockedIndefinitelyOnIVar
tryWrite :: IVar a -> a -> IO Bool
tryWrite (IVar lock trans _) value = block $ do
a <- tryTakeMVar lock
case a of
Just _ -> putMVar trans value >> return True
Nothing -> return False
#if __GLASGOW_HASKELL__ >= 708
where
block = mask_
#endif
data BlockedIndefinitelyOnIVar = BlockedIndefinitelyOnIVar
deriving (Typeable)
instance Exception BlockedIndefinitelyOnIVar
instance Show BlockedIndefinitelyOnIVar where
showsPrec _ BlockedIndefinitelyOnIVar =
showString "thread blocked indefinitely writing full IVar"