-- |Data.AVar.Unsafe has a similar interface to Data.AVar, but instead of letting -- the user handle exceptions from Eithers, it will throw exceptions caught by -- the variable. module Data.AVar.Unsafe ( AVar, Result(..), getAVar, putAVar, modAVar, modAVar', justModAVar, condModAVar, swapAVar, newAVar) where import Data.AVar.Internal import Control.Concurrent import Control.Concurrent.MVar import Control.Concurrent.Chan import qualified Control.Exception as E data Result = OK -- |'getAVar' reads the current value inside the AVar. getAVar :: AVar a -> IO a getAVar (AVar chan) = do res <- newEmptyMVar writeChan chan (Get res) takeMVar res -- |'putAVar' replaces the currect value in the variable with the given x putAVar :: AVar a -> a -> IO () putAVar (AVar chan) x = writeChan chan (Put x) -- |'modAVar' takes a function from a to a, and modifies the variable. It will -- throw any exceptions caught by the variable when applying the function. modAVar :: AVar a -> (a -> a) -> IO () modAVar (AVar chan) f = do res <- newEmptyMVar writeChan chan (Mod f res) r <- takeMVar res case r of Nothing -> return () Just e -> E.throw e -- |'modAVar'' is like modAVar, but it modifies the variable, along with -- returning a result of type b. It also throws any errors caugh by the variable. modAVar' :: AVar a -> (a -> (a,b)) -> IO b modAVar' (AVar chan) f = do res <- newEmptyMVar writeChan chan (Mod' f res) r <- takeMVar res case r of Right b -> return b Left e -> E.throw e -- |'justModAVar' will attempt to run the given function on the variable. -- It does not report back on its sucess or failure, and if the function -- produces an exception, the variable is left unchanged. It should be -- used when you just want to modify the variable, and keep running, -- without waiting for the action to complete. justModAVar :: AVar a -> (a -> a) -> IO () justModAVar (AVar chan) f = writeChan chan (JustMod f) -- |'condModAVar' applies the first finction to the current value in the -- AVar, and will modify the value using the second function if -- it results in 'True', or the third function if it results in 'Fasle'. condModAVar :: AVar a -> (a -> Bool) -> (a -> a) -> (a -> a) -> IO Bool condModAVar (AVar chan) p t f = do res <- newEmptyMVar writeChan chan (Atom p t f res) r <- takeMVar res case r of Right x -> return x Left e -> E.throw e -- |'swapAVar' takes a new value, puts it into the AVar, and returns the old value. swapAVar :: (AVar a) -> a -> IO a swapAVar (AVar chan) new = do res <- newEmptyMVar writeChan chan (Mod' (\old -> (new, old)) res) r <- takeMVar res case r of Right a -> return a Left e -> E.throw e