module Reactor.BSem (
BSem,
newBSem,
newLockedBSem,
tryAcquireBSems,
tryAcquireBSemsWithError,
tryAcquireBSemsWithError1,
) where
import Data.Maybe
import Control.Concurrent.MVar
import Util.Computation
import Events.Synchronized
import Reactor.Lock
newtype BSem = BSem (MVar ()) deriving Eq
instance Lock BSem where
acquire (BSem sem) = takeMVar sem
release (BSem sem) = putMVar sem ()
tryAcquire (BSem sem) =
do
success <- tryTakeMVar sem
return (isJust success)
instance Synchronized BSem where
synchronize (BSem sem) c =
do
takeMVar sem
ans <- try c
putMVar sem ()
propagate ans
newBSem :: IO BSem
newBSem = newMVar () >>= return . BSem
newLockedBSem :: IO BSem
newLockedBSem = newEmptyMVar >>= return . BSem
tryAcquireBSems :: [BSem] -> IO (Maybe (IO ()))
tryAcquireBSems bSems =
do
let
toMess _ = return ""
actWithError <- tryAcquireBSemsWithError id toMess bSems
return (case fromWithError actWithError of
Left _ -> Nothing
Right act -> Just act
)
tryAcquireBSemsWithError :: (object -> BSem) -> (object -> IO String)
-> [object] -> IO (WithError (IO ()))
tryAcquireBSemsWithError toBSem toMess objects =
let
getBSem object = return (toBSem object)
getMessIfError object =
do
mess <- toMess object
return (Just mess)
in
tryAcquireBSemsWithError1 getBSem getMessIfError objects
tryAcquireBSemsWithError1 ::
(object -> IO BSem) -> (object -> IO (Maybe String)) -> [object]
-> IO (WithError (IO ()))
tryAcquireBSemsWithError1 _ _ [] = return . return $ done
tryAcquireBSemsWithError1 getBSem getMessIfError (object:objects) =
do
bSem <- getBSem object
acquire1 <- tryAcquire bSem
if acquire1
then
do
acquires
<- tryAcquireBSemsWithError1 getBSem getMessIfError objects
case fromWithError acquires of
Right releaseAct ->
return (return (
do
releaseAct
release bSem
))
Left _ ->
do
release bSem
return acquires
else
do
errorMessIfError <- getMessIfError object
case errorMessIfError of
Just errorMess -> return (fail errorMess)
Nothing ->
tryAcquireBSemsWithError1 getBSem getMessIfError objects