------------------------------------------------------------------------------- |-- Module : Control.Concurrent.SampleVar-- Copyright : (c) The University of Glasgow 2001-- License : BSD-style (see the file libraries/base/LICENSE)-- -- Maintainer : libraries@haskell.org-- Stability : experimental-- Portability : non-portable (concurrency)---- Sample variables-------------------------------------------------------------------------------moduleControl.Concurrent.SampleVar(-- * Sample VariablesSampleVar,-- :: type _ =newEmptySampleVar,-- :: IO (SampleVar a)newSampleVar,-- :: a -> IO (SampleVar a)emptySampleVar,-- :: SampleVar a -> IO ()readSampleVar,-- :: SampleVar a -> IO awriteSampleVar,-- :: SampleVar a -> a -> IO ()isEmptySampleVar,-- :: SampleVar a -> IO Bool)whereimportPreludeimportControl.Concurrent.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 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 a filled 'SampleVar' overwrites the current value.-- (different from 'putMVar' on full 'MVar'.)typeSampleVara=MVar(Int,-- 1 == full-- 0 == empty-- <0 no of readers blockedMVara)-- |Build a new, empty, 'SampleVar'newEmptySampleVar::IO(SampleVara)newEmptySampleVar=dov<-newEmptyMVarnewMVar(0,v)-- |Build a 'SampleVar' with an initial value.newSampleVar::a->IO(SampleVara)newSampleVara=dov<-newMVaranewMVar(1,v)-- |If the SampleVar is full, leave it empty. Otherwise, do nothing.emptySampleVar::SampleVara->IO()emptySampleVarv=do(readers,var)<-takeMVarvifreaders>0thendo_<-takeMVarvarputMVarv(0,var)elseputMVarv(readers,var)-- |Wait for a value to become available, then take it and return.readSampleVar::SampleVara->IOareadSampleVarsvar=do---- filled => make empty and grab sample-- not filled => try to grab value, empty when read val.--(readers,val)<-takeMVarsvarputMVarsvar(readers-1,val)takeMVarval-- |Write a value into the 'SampleVar', overwriting any previous value that-- was there.writeSampleVar::SampleVara->a->IO()writeSampleVarsvarv=do---- filled => overwrite-- not filled => fill, write val--(readers,val)<-takeMVarsvarcasereadersof1->swapMVarvalv>>putMVarsvar(1,val)_->putMVarvalv>>putMVarsvar(min1(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::SampleVara->IOBoolisEmptySampleVarsvar=do(readers,_)<-readMVarsvarreturn(readers==0)