X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FConcurrent%2FSampleVar.hs;h=68e4b308d69bb76f2eb33944425b785ec98329aa;hb=1307901a3528834b706eb9336bd0a3ba88fe09f3;hp=bdf5eac68da0a39d964f91954e22895c34a4da50;hpb=8c689077e1b645cc41fc24b8929b75d8653acca1;p=ghc-base.git diff --git a/Control/Concurrent/SampleVar.hs b/Control/Concurrent/SampleVar.hs index bdf5eac..68e4b30 100644 --- a/Control/Concurrent/SampleVar.hs +++ b/Control/Concurrent/SampleVar.hs @@ -30,6 +30,10 @@ import Prelude import Control.Concurrent.MVar +import Control.Exception ( mask_ ) + +import Data.Functor ( (<$>) ) + -- | -- Sample variables are slightly different from a normal 'MVar': -- @@ -46,61 +50,65 @@ import Control.Concurrent.MVar -- * Writing to a filled 'SampleVar' overwrites the current value. -- (different from 'putMVar' on full 'MVar'.) -type SampleVar a - = MVar (Int, -- 1 == full - -- 0 == empty - -- <0 no of readers blocked - MVar a) +newtype SampleVar a = SampleVar ( MVar ( Int -- 1 == full + -- 0 == empty + -- <0 no of readers blocked + , MVar a + ) + ) + deriving (Eq) -- |Build a new, empty, 'SampleVar' newEmptySampleVar :: IO (SampleVar a) newEmptySampleVar = do v <- newEmptyMVar - newMVar (0,v) + SampleVar <$> newMVar (0,v) -- |Build a 'SampleVar' with an initial value. newSampleVar :: a -> IO (SampleVar a) newSampleVar a = do v <- newMVar a - newMVar (1,v) + SampleVar <$> newMVar (1,v) -- |If the SampleVar is full, leave it empty. Otherwise, do nothing. emptySampleVar :: SampleVar a -> IO () -emptySampleVar v = do - (readers, var) <- takeMVar v +emptySampleVar (SampleVar v) = mask_ $ do + s@(readers, var) <- takeMVar v if readers > 0 then do - takeMVar var + _ <- takeMVar var putMVar v (0,var) else - putMVar v (readers,var) + putMVar v s -- |Wait for a value to become available, then take it and return. readSampleVar :: SampleVar a -> IO a -readSampleVar svar = do +readSampleVar (SampleVar svar) = mask_ $ do -- -- filled => make empty and grab sample -- not filled => try to grab value, empty when read val. -- (readers,val) <- takeMVar svar - putMVar svar (readers-1,val) + let readers' = readers-1 + readers' `seq` putMVar svar (readers',val) takeMVar val -- |Write a value into the 'SampleVar', overwriting any previous value that -- was there. writeSampleVar :: SampleVar a -> a -> IO () -writeSampleVar svar v = do +writeSampleVar (SampleVar svar) v = mask_ $ do -- -- filled => overwrite -- not filled => fill, write val -- - (readers,val) <- takeMVar svar + s@(readers,val) <- takeMVar svar case readers of - 1 -> - swapMVar val v >> - putMVar svar (1,val) - _ -> - putMVar val v >> - putMVar svar (min 1 (readers+1), val) + 1 -> + swapMVar val v >> + putMVar svar s + _ -> + putMVar val v >> + let readers' = min 1 (readers+1) + in readers' `seq` putMVar svar (readers', val) -- | Returns 'True' if the 'SampleVar' is currently empty. -- @@ -110,7 +118,7 @@ writeSampleVar svar v = do -- you see the result of 'isEmptySampleVar'. -- isEmptySampleVar :: SampleVar a -> IO Bool -isEmptySampleVar svar = do +isEmptySampleVar (SampleVar svar) = do (readers, _) <- readMVar svar - return (readers == 0) + return (readers <= 0)