AVar 0.0.2 → 0.0.3
raw patch · 2 files changed
+39/−22 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.AVar: JustMod :: (a -> a) -> Transaction a
+ Data.AVar: justModAVar :: AVar a -> (a -> a) -> IO ()
+ Data.AVar: putAVar :: AVar a -> a -> IO ()
Files
- AVar.cabal +1/−1
- Data/AVar.hs +38/−21
AVar.cabal view
@@ -1,5 +1,5 @@ Name: AVar-Version: 0.0.2+Version: 0.0.3 Category: Concurrency Synopsis: Mutable variables with Exception handling and concurrency support. Description: AVars emulate mutable variables, by providing a queue based interface to interacting with the variable. Each variable runs a 'handler' function, which reads requests from a queue and processes them one by one. They can be used in concurrent systems safely, and should handle exceptions thrown by modifying functions gracefully.
Data/AVar.hs view
@@ -6,17 +6,29 @@ -- |AVars are a form of transactional variables. They internally use a tail -- recursive function to carry the 'state' of the variable, and allow for--- use in concurrent systems, where actions are quaranteed to happen. They--- are designed to cope with exceptions thrown by any modifying functions.+-- use in concurrent systems, where actions are guaranteed to happen. They+-- are designed to cope with exceptions thrown by any modifying functions;+-- any exception thrown during a transaction will either be passed back to+-- the caller or ignored, and the variable keeps on running.+--+-- They are handy for applications like keeping track of resources by+-- incrementing and decrementing the variable. They should not be used in+-- a way which you would read the variable, then modify it based on the+-- result recieved, but rather using the provided functions. If this was+-- not done, the variable's value is very likely to have changed in the+-- mean time.+ module Data.AVar ( -- * Types AVar, Transaction(..), -- * functions on AVars+ putAVar, newAVar, putMVar, modAVar, modAVar',+ justModAVar, getAVar, condModAVar, swapAVar) where@@ -24,7 +36,6 @@ import Control.Concurrent.MVar import Control.Concurrent.Chan import qualified Control.Exception as E-import System.Environment -- * Types @@ -37,6 +48,8 @@ -- ^reads the variable | Mod (a -> a) (MVar (Maybe E.SomeException)) -- ^modifies the variable+ | JustMod (a -> a)+ -- ^ Just modifies the variable (unless an exception occurs) | forall b. Mod' (a -> (a,b)) (MVar (Either E.SomeException b)) -- ^ modifies the variable, returning the b result to the caller | Atom (a -> Bool) (a -> a) (a -> a) (MVar (Either E.SomeException Bool))@@ -81,6 +94,12 @@ case p of Nothing -> handler chan x' _ -> handler chan x+ JustMod f -> do+ let x' = f x+ res <- E.try (E.evaluate x')+ case res of+ Right _ -> handler chan x'+ Left (_::E.SomeException) -> handler chan x Mod' f mvar -> do let y@(a,b) = f x@@ -118,6 +137,15 @@ -- putMVar res False -- handler chan (n x) ++-- |'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)@@ -138,12 +166,13 @@ writeChan chan (Mod' f res) takeMVar res --- |'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+-- |'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 if true will modify the value using the second function if@@ -164,18 +193,6 @@ res <- newEmptyMVar writeChan chan (Mod' (\old -> (new, old)) res) takeMVar res--main = do- n <- getArgs >>= \xs -> if null xs then return 1000000 else (readIO.head) xs- var <- newAVar (0 :: Int)- m <- newEmptyMVar- forkIO $ test n var m- takeMVar m- where test 0 _ m = putMVar m ()- test n var m = do- res <- getAVar var- putAVar var (res + 1)- test (n-1) var m