X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FConcurrent%2FSampleVar.hs;h=4d88a19cd3f343bb557da03e50b6b30cf4e24710;hb=6b1a36a595eddf1e124529646afdb75c76a9966d;hp=2b2909257ac578bd87db1516315f847f43e6cd3e;hpb=f7a485978f04e84b086f1974b88887cc72d832d0;p=haskell-directory.git diff --git a/Control/Concurrent/SampleVar.hs b/Control/Concurrent/SampleVar.hs index 2b29092..4d88a19 100644 --- a/Control/Concurrent/SampleVar.hs +++ b/Control/Concurrent/SampleVar.hs @@ -6,7 +6,7 @@ -- -- Maintainer : libraries@haskell.org -- Stability : experimental --- Portability : non-portable +-- Portability : non-portable (concurrency) -- -- Sample variables -- @@ -14,13 +14,15 @@ module Control.Concurrent.SampleVar ( + -- * Sample Variables SampleVar, -- :: type _ = newEmptySampleVar, -- :: IO (SampleVar a) newSampleVar, -- :: a -> IO (SampleVar a) emptySampleVar, -- :: SampleVar a -> IO () readSampleVar, -- :: SampleVar a -> IO a - writeSampleVar -- :: SampleVar a -> a -> IO () + writeSampleVar, -- :: SampleVar a -> a -> IO () + isEmptySampleVar, -- :: SampleVar a -> IO Bool ) where @@ -28,20 +30,21 @@ import Prelude import Control.Concurrent.MVar --- Sample variables are slightly different from a normal MVar: +-- | +-- Sample variables are slightly different from a normal 'MVar': -- --- * Reading an empty SampleVar causes the reader to block. --- (same as takeMVar on empty MVar) +-- * Reading an empty 'SampleVar' causes the reader to block. +-- (same as 'takeMVar' on empty 'MVar') -- --- * Reading a filled SampleVar empties it and returns value. --- (same as takeMVar) +-- * Reading a filled 'SampleVar' empties it and returns value. +-- (same as 'takeMVar') -- --- * Writing to an empty SampleVar fills it with a value, and --- potentially, wakes up a blocked reader (same as for putMVar on --- empty MVar). +-- * Writing to an empty 'SampleVar' fills it with a value, and +-- potentially, wakes up a blocked reader (same as for 'putMVar' on +-- empty 'MVar'). -- --- * Writing to a filled SampleVar overwrites the current value. --- (different from putMVar on full MVar.) +-- * Writing to a filled 'SampleVar' overwrites the current value. +-- (different from 'putMVar' on full 'MVar'.) type SampleVar a = MVar (Int, -- 1 == full @@ -49,43 +52,48 @@ type SampleVar a -- <0 no of readers blocked MVar a) --- Initally, a SampleVar is empty/unfilled. - +-- |Build a new, empty, 'SampleVar' newEmptySampleVar :: IO (SampleVar a) newEmptySampleVar = do v <- newEmptyMVar newMVar (0,v) +-- |Build a 'SampleVar' with an initial value. newSampleVar :: a -> IO (SampleVar a) newSampleVar a = do v <- newEmptyMVar putMVar v a 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 - if readers >= 0 then + if readers > 0 then do + takeMVar var putMVar v (0,var) else putMVar v (readers,var) +-- |Wait for a value to become available, then take it and return. +readSampleVar :: SampleVar a -> IO a +readSampleVar svar = do -- -- filled => make empty and grab sample -- not filled => try to grab value, empty when read val. -- -readSampleVar :: SampleVar a -> IO a -readSampleVar svar = do (readers,val) <- takeMVar svar putMVar svar (readers-1,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 -- -- filled => overwrite -- not filled => fill, write val -- -writeSampleVar :: SampleVar a -> a -> IO () -writeSampleVar svar v = do (readers,val) <- takeMVar svar case readers of 1 -> @@ -94,3 +102,16 @@ writeSampleVar svar v = do _ -> putMVar val v >> putMVar svar (min 1 (readers+1), val) + +-- | Returns 'True' if the 'SampleVar' is currently empty. +-- +-- Note that this function is only useful if you know that no other +-- threads can be modifying the state of the 'SampleVar', because +-- otherwise the state of the 'SampleVar' may have changed by the time +-- you see the result of 'isEmptySampleVar'. +-- +isEmptySampleVar :: SampleVar a -> IO Bool +isEmptySampleVar svar = do + (readers,val) <- readMVar svar + return (readers == 0) +