-- | -- Module : Simulation.Aivika.Experiment.Concurrent.MVar -- Copyright : Copyright (c) 2012-2017, David Sorokin -- License : BSD3 -- Maintainer : David Sorokin -- Stability : experimental -- Tested with: GHC 8.0.1 -- -- The module defines helper functions for working with synchronized variable 'MVar'. -- module Simulation.Aivika.Experiment.Concurrent.MVar (maybeReadMVar, maybePutMVar) where import Control.Exception import Control.Concurrent.MVar import Data.Maybe -- | Like 'maybe' but for the synchronized variable. maybeReadMVar :: b -> (a -> IO b) -> MVar (Maybe a) -> IO b maybeReadMVar b0 f x = do a <- readMVar x case a of Just a -> f a Nothing -> return b0 -- | Update the contents if the variable was empty and then return a result of -- applying the specified function to either the initial or current value. maybePutMVar :: MVar (Maybe a) -> IO a -> (a -> IO b) -> IO b maybePutMVar x m0 f = mask_ $ do a <- takeMVar x case a of Just a -> do putMVar x (Just a) f a Nothing -> do let handle :: SomeException -> IO a handle e = do putMVar x Nothing throw e a0 <- catch m0 handle putMVar x (Just a0) f a0