packages feed

concurrency 1.1.1.0 → 1.1.2.0

raw patch · 15 files changed

+489/−23 lines, 15 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Control.Concurrent.Classy.Async: concurrently_ :: MonadConc m => m a -> m b -> m ()
+ Control.Concurrent.Classy.Async: forConcurrently_ :: (Foldable f, MonadConc m) => f a -> (a -> m b) -> m ()
+ Control.Concurrent.Classy.Async: instance (Control.Monad.Conc.Class.MonadConc m, Data.Semigroup.Semigroup a) => Data.Semigroup.Semigroup (Control.Concurrent.Classy.Async.Concurrently m a)
+ Control.Concurrent.Classy.Async: instance (Control.Monad.Conc.Class.MonadConc m, GHC.Base.Monoid a) => GHC.Base.Monoid (Control.Concurrent.Classy.Async.Concurrently m a)
+ Control.Concurrent.Classy.Async: mapConcurrently_ :: (Foldable f, MonadConc m) => (a -> m b) -> f a -> m ()
+ Control.Concurrent.Classy.Async: replicateConcurrently :: MonadConc m => Int -> m a -> m [a]
+ Control.Concurrent.Classy.Async: replicateConcurrently_ :: MonadConc m => Int -> m a -> m ()
+ Control.Concurrent.Classy.Async: uninterruptibleCancel :: MonadConc m => Async m a -> m ()
+ Control.Monad.Conc.Class: mask_ :: MonadMask m => m a -> m a
+ Control.Monad.Conc.Class: uninterruptibleMask_ :: MonadMask m => m a -> m a

Files

Control/Concurrent/Classy/Async.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP        #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE RankNTypes #-}  -- | This module is a version of the@@ -47,6 +47,7 @@   , poll, pollSTM   , waitCatch, waitCatchSTM   , cancel+  , uninterruptibleCancel   , cancelWith   , asyncThreadId @@ -69,9 +70,10 @@   -- * Convenient utilities   , race   , race_-  , concurrently-  , mapConcurrently-  , forConcurrently+  , concurrently, concurrently_+  , mapConcurrently, mapConcurrently_+  , forConcurrently, forConcurrently_+  , replicateConcurrently, replicateConcurrently_   , Concurrently(..)   ) where @@ -82,9 +84,11 @@ import Control.Monad.Catch (finally, try, onException) import Control.Monad.Conc.Class import Control.Monad.STM.Class--#if !MIN_VERSION_base(4,8,0)+import Data.Foldable (foldMap) import Data.Traversable++#if MIN_VERSION_base(4,9,0)+import Data.Semigroup (Semigroup(..)) #endif  -----------------------------------------------------------------------------------------@@ -98,14 +102,18 @@ -- Note that, unlike the \"async\" package, 'Async' here does not have -- an 'Ord' instance. This is because 'MonadConc' 'ThreadId's do not -- necessarily have one.+--+-- @since 1.1.1.0 data Async m a = Async   { asyncThreadId :: !(ThreadId m)   , _asyncWait :: STM m (Either SomeException a)   } +-- | @since 1.1.1.0 instance MonadConc m => Eq (Async m a) where   Async t1 _ == Async t2 _ = t1 == t2 +-- | @since 1.1.1.0 instance MonadConc m => Functor (Async m) where   fmap f (Async t w) = Async t $ fmap f <$> w @@ -124,40 +132,65 @@ -- >   <$> Concurrently (getURL "url1") -- >   <*> Concurrently (getURL "url2") -- >   <*> Concurrently (getURL "url3")+--+-- @since 1.1.1.0 newtype Concurrently m a = Concurrently { runConcurrently :: m a } +-- | @since 1.1.1.0 instance MonadConc m => Functor (Concurrently m) where   fmap f (Concurrently a) = Concurrently $ f <$> a +-- | @since 1.1.1.0 instance MonadConc m => Applicative (Concurrently m) where   pure = Concurrently . return    Concurrently fs <*> Concurrently as =     Concurrently $ (\(f, a) -> f a) <$> concurrently fs as +-- | @since 1.1.1.0 instance MonadConc m => Alternative (Concurrently m) where   empty = Concurrently $ forever yield    Concurrently as <|> Concurrently bs =     Concurrently $ either id id <$> race as bs +#if MIN_VERSION_base(4,9,0)+-- | Only defined for base >= 4.9.0.0+--+-- @since 1.1.2.0+instance (MonadConc m, Semigroup a) => Semigroup (Concurrently m a) where+  (<>) = liftA2 (<>)+#endif +-- | @since 1.1.2.0+instance (MonadConc m, Monoid a) => Monoid (Concurrently m a) where+  mempty = pure mempty+  mappend = liftA2 mappend+ ------------------------------------------------------------------------------- -- Spawning  -- | Spawn an asynchronous action in a separate thread.+--+-- @since 1.1.1.0 async :: MonadConc m => m a -> m (Async m a) async = asyncUsing fork  -- | Like 'async' but using 'forkOn' internally.+--+-- @since 1.1.1.0 asyncOn :: MonadConc m => Int -> m a -> m (Async m a) asyncOn = asyncUsing . forkOn  -- | Like 'async' but using 'forkWithUnmask' internally.+--+-- @since 1.1.1.0 asyncWithUnmask :: MonadConc m => ((forall b. m b -> m b) -> m a) -> m (Async m a) asyncWithUnmask = asyncUnmaskUsing forkWithUnmask  -- | Like 'asyncOn' but using 'forkOnWithUnmask' internally.+--+-- @since 1.1.1.0 asyncOnWithUnmask :: MonadConc m => Int -> ((forall b. m b -> m b) -> m a) -> m (Async m a) asyncOnWithUnmask i = asyncUnmaskUsing (forkOnWithUnmask i) @@ -180,27 +213,35 @@  -- | Spawn an asynchronous action in a separate thread, and pass its -- @Async@ handle to the supplied function. When the function returns--- or throws an exception, 'cancel' is called on the @Async@.+-- or throws an exception, 'uninterruptibleCancel' is called on the @Async@. ----- > withAsync action inner = bracket (async action) cancel inner+-- > withAsync action inner = bracket (async action) uninterruptiblCancel inner -- -- This is a useful variant of 'async' that ensures an @Async@ is -- never left running unintentionally. ----- Since 'cancel' may block, 'withAsync' may also block; see 'cancel'--- for details.+-- Since 'uninterruptibleCancel' may block, 'withAsync' may also+-- block; see 'uninterruptibleCancel' for details.+--+-- @since 1.1.1.0 withAsync :: MonadConc m => m a -> (Async m a -> m b) -> m b withAsync = withAsyncUsing fork  -- | Like 'withAsync' but uses 'forkOn' internally.+--+-- @since 1.1.1.0 withAsyncOn :: MonadConc m => Int -> m a -> (Async m a -> m b) -> m b withAsyncOn = withAsyncUsing . forkOn  -- | Like 'withAsync' bit uses 'forkWithUnmask' internally.+--+-- @since 1.1.1.0 withAsyncWithUnmask :: MonadConc m => ((forall x. m x -> m x) -> m a) -> (Async m a -> m b) -> m b withAsyncWithUnmask = withAsyncUnmaskUsing forkWithUnmask  -- | Like 'withAsyncOn' bit uses 'forkOnWithUnmask' internally.+--+-- @since 1.1.1.0 withAsyncOnWithUnmask :: MonadConc m => Int -> ((forall x. m x -> m x) -> m a) -> (Async m a -> m b) -> m b withAsyncOnWithUnmask i = withAsyncUnmaskUsing (forkOnWithUnmask i) @@ -216,7 +257,7 @@    let a = Async tid (readTMVar var) -  res <- inner a `catchAll` (\e -> cancel a >> throw e)+  res <- inner a `catchAll` (\e -> uninterruptibleCancel a >> throw e)   cancel a    return res@@ -230,7 +271,7 @@    let a = Async tid (readTMVar var) -  res <- inner a `catchAll` (\e -> cancel a >> throw e)+  res <- inner a `catchAll` (\e -> uninterruptibleCancel a >> throw e)   cancel a    return res@@ -246,10 +287,14 @@ -- exception is re-thrown by 'wait'. -- -- > wait = atomically . waitSTM+--+-- @since 1.1.1.0 wait :: MonadConc m => Async m a -> m a wait = atomically . waitSTM  -- | A version of 'wait' that can be used inside a @MonadSTM@ transaction.+--+-- @since 1.1.1.0 waitSTM :: MonadConc m => Async m a -> STM m a waitSTM a = do  r <- waitCatchSTM a@@ -261,39 +306,59 @@ -- exception @x@, or @Right a@ if it returned a value @a@. -- -- > poll = atomically . pollSTM+--+-- @since 1.1.1.0 poll :: MonadConc m => Async m a -> m (Maybe (Either SomeException a)) poll = atomically . pollSTM  -- | A version of 'poll' that can be used inside a @MonadSTM@ transaction.+--+-- @since 1.1.1.0 pollSTM :: MonadConc m => Async m a -> STM m (Maybe (Either SomeException a)) pollSTM (Async _ w) = (Just <$> w) `orElse` return Nothing  -- | Wait for an asynchronous action to complete, and return either -- @Left e@ if the action raised an exception @e@, or @Right a@ if it -- returned a value @a@.+--+-- @since 1.1.1.0 waitCatch :: MonadConc m => Async m a -> m (Either SomeException a) waitCatch = tryAgain . atomically . waitCatchSTM where   -- See: https://github.com/simonmar/async/issues/14   tryAgain f = f `catch` \BlockedIndefinitelyOnSTM -> f  -- | A version of 'waitCatch' that can be used inside a @MonadSTM@ transaction.+--+-- @since 1.1.1.0 waitCatchSTM :: MonadConc m => Async m a -> STM m (Either SomeException a) waitCatchSTM (Async _ w) = w  -- | Cancel an asynchronous action by throwing the @ThreadKilled@--- exception to it. Has no effect if the 'Async' has already--- completed.+-- exception to it, and waiting for the 'Async' thread to quit. Has no+-- effect if the 'Async' has already completed. ----- > cancel a = throwTo (asyncThreadId a) ThreadKilled+-- > cancel a = throwTo (asyncThreadId a) ThreadKilled <* waitCatch a ----- Note that 'cancel' is synchronous in the same sense as 'throwTo'.--- It does not return until the exception has been thrown in the--- target thread, or the target thread has completed. An asynchronous--- 'cancel' can of course be obtained by wrapping 'cancel' itself in--- 'async'.+-- Note that 'cancel' will not terminate until the thread the 'Async'+-- refers to has terminated. This means that 'cancel' will block for+-- as long as said thread blocks when receiving an asynchronous+-- exception.+--+-- An asynchronous 'cancel' can of course be obtained by wrapping+-- 'cancel' itself in 'async'.+--+-- @since 1.1.1.0 cancel :: MonadConc m => Async m a -> m ()-cancel (Async tid _) = throwTo tid ThreadKilled+cancel a@(Async tid _) = throwTo tid ThreadKilled <* waitCatch a +-- | Cancel an asynchronous action.+--+-- This is a variant of 'cancel' but it is not interruptible.+--+-- @since 1.1.2.0+uninterruptibleCancel :: MonadConc m => Async m a -> m ()+uninterruptibleCancel = uninterruptibleMask_ . cancel+ -- | Cancel an asynchronous action by throwing the supplied exception -- to it. --@@ -301,6 +366,8 @@ -- -- The notes about the synchronous nature of 'cancel' also apply to -- 'cancelWith'.+--+-- @since 1.1.1.0 cancelWith :: (MonadConc m, Exception e) => Async m a -> e -> m () cancelWith (Async tid _) = throwTo tid @@ -314,11 +381,15 @@ -- -- If multiple 'Async's complete or have completed, then the value -- returned corresponds to the first completed 'Async' in the list.+--+-- @since 1.1.1.0 waitAny :: MonadConc m => [Async m a] -> m (Async m a, a) waitAny = atomically . waitAnySTM  -- | A version of 'waitAny' that can be used inside a @MonadSTM@ -- transaction.+--+-- @since 1.1.1.0 waitAnySTM :: MonadConc m => [Async m a] -> STM m (Async m a, a) waitAnySTM = foldr (orElse . (\a -> do r <- waitSTM a; return (a, r))) retry @@ -328,43 +399,59 @@ -- -- If multiple 'Async's complete or have completed, then the value -- returned corresponds to the first completed 'Async' in the list.+--+-- @since 1.1.1.0 waitAnyCatch :: MonadConc m => [Async m a] -> m (Async m a, Either SomeException a) waitAnyCatch = atomically . waitAnyCatchSTM  -- | A version of 'waitAnyCatch' that can be used inside a @MonadSTM@ -- transaction.+--+-- @since 1.1.1.0 waitAnyCatchSTM :: MonadConc m => [Async m a] -> STM m (Async m a, Either SomeException a) waitAnyCatchSTM = foldr (orElse . (\a -> do r <- waitCatchSTM a; return (a, r))) retry  -- | Like 'waitAny', but also cancels the other asynchronous -- operations as soon as one has completed.+--+-- @since 1.1.1.0 waitAnyCancel :: MonadConc m => [Async m a] -> m (Async m a, a) waitAnyCancel asyncs = waitAny asyncs `finally` mapM_ cancel asyncs  -- | Like 'waitAnyCatch', but also cancels the other asynchronous -- operations as soon as one has completed.+--+-- @since 1.1.1.0 waitAnyCatchCancel :: MonadConc m => [Async m a] -> m (Async m a, Either SomeException a) waitAnyCatchCancel asyncs = waitAnyCatch asyncs `finally` mapM_ cancel asyncs  -- | Wait for the first of two @Async@s to finish.  If the @Async@ -- that finished first raised an exception, then the exception is -- re-thrown by 'waitEither'.+--+-- @since 1.1.1.0 waitEither :: MonadConc m => Async m a -> Async m b -> m (Either a b) waitEither left right = atomically $ waitEitherSTM left right  -- | A version of 'waitEither' that can be used inside a @MonadSTM@ -- transaction.+--+-- @since 1.1.1.0 waitEitherSTM :: MonadConc m => Async m a -> Async m b -> STM m (Either a b) waitEitherSTM left right =   (Left <$> waitSTM left) `orElse` (Right <$> waitSTM right)  -- | Wait for the first of two @Async@s to finish.+--+-- @since 1.1.1.0 waitEitherCatch :: MonadConc m => Async m a -> Async m b   -> m (Either (Either SomeException a) (Either SomeException b)) waitEitherCatch left right = atomically $ waitEitherCatchSTM left right  -- | A version of 'waitEitherCatch' that can be used inside a -- @MonadSTM@ transaction.+--+-- @since 1.1.1.0 waitEitherCatchSTM :: MonadConc m => Async m a -> Async m b   -> STM m (Either (Either SomeException a) (Either SomeException b)) waitEitherCatchSTM left right =@@ -372,34 +459,46 @@  -- | Like 'waitEither', but also 'cancel's both @Async@s before -- returning.+--+-- @since 1.1.1.0 waitEitherCancel :: MonadConc m => Async m a -> Async m b -> m (Either a b) waitEitherCancel left right =   waitEither left right `finally` (cancel left >> cancel right)  -- | Like 'waitEitherCatch', but also 'cancel's both @Async@s before -- returning.+--+-- @since 1.1.1.0 waitEitherCatchCancel :: MonadConc m => Async m a -> Async m b   -> m (Either (Either SomeException a) (Either SomeException b)) waitEitherCatchCancel left right =   waitEitherCatch left right `finally` (cancel left >> cancel right)  -- | Like 'waitEither', but the result is ignored.+--+-- @since 1.1.1.0 waitEither_ :: MonadConc m => Async m a -> Async m b -> m () waitEither_ left right = atomically $ waitEitherSTM_ left right  -- | A version of 'waitEither_' that can be used inside a @MonadSTM@ -- transaction.+--+-- @since 1.1.1.0 waitEitherSTM_:: MonadConc m => Async m a -> Async m b -> STM m () waitEitherSTM_ left right = void $ waitEitherSTM left right  -- | Waits for both @Async@s to finish, but if either of them throws -- an exception before they have both finished, then the exception is -- re-thrown by 'waitBoth'.+--+-- @since 1.1.1.0 waitBoth :: MonadConc m => Async m a -> Async m b -> m (a, b) waitBoth left right = atomically $ waitBothSTM left right  -- | A version of 'waitBoth' that can be used inside a @MonadSTM@ -- transaction.+--+-- @since 1.1.1.0 waitBothSTM :: MonadConc m => Async m a -> Async m b -> STM m (a, b) waitBothSTM left right = do   a <- waitSTM left `orElse` (waitSTM right >> retry)@@ -414,6 +513,7 @@ -- @Async@ raises an exception, that exception will be re-thrown in -- the current thread. --+-- @since 1.1.1.0 link :: MonadConc m => Async m a -> m () link (Async _ w) = do   me <- myThreadId@@ -425,6 +525,8 @@  -- | Link two @Async@s together, such that if either raises an -- exception, the same exception is re-thrown in the other @Async@.+--+-- @since 1.1.1.0 link2 :: MonadConc m => Async m a -> Async m b -> m () link2 left@(Async tl _)  right@(Async tr _) =   void $ forkRepeat $ do@@ -458,6 +560,7 @@ -- >   withAsync right $ \b -> -- >   waitEither a b --+-- @since 1.1.1.0 race :: MonadConc m => m a -> m b -> m (Either a b) race left right = concurrently' left right collect where   collect m = do@@ -472,6 +575,8 @@ -- >   withAsync left $ \a -> -- >   withAsync right $ \b -> -- >   waitEither_ a b+--+-- @since 1.1.1.0 race_ :: MonadConc m => m a -> m b -> m () race_ a b = void $ race a b @@ -484,6 +589,8 @@ -- >   withAsync left $ \a -> -- >   withAsync right $ \b -> -- >   waitBoth a b+--+-- @since 1.1.1.0 concurrently :: MonadConc m => m a -> m b -> m (a, b) concurrently left right = concurrently' left right (collect []) where   collect [Left a, Right b] _ = return (a, b)@@ -494,6 +601,18 @@       Left ex -> throw ex       Right r -> collect (r:xs) m +-- | 'concurrently_' is 'concurrently' but ignores the return values.+--+-- @since 1.1.2.0+concurrently_ :: MonadConc m => m a -> m b -> m ()+concurrently_ left right = concurrently' left right (collect 0) where+  collect 2 _ = pure ()+  collect i m = do+    e <- takeMVar m+    case e of+      Left ex -> throw ex+      Right _ -> collect (i+1::Int) m+ -- Run two things concurrently. Faster than the 'Async' version. concurrently' :: MonadConc m => m a -> m b   -> (MVar m (Either SomeException (Either a b)) -> m r)@@ -525,6 +644,7 @@ -- -- > pages <- mapConcurrently getURL ["url1", "url2", "url3"] --+-- @since 1.1.1.0 mapConcurrently :: (Traversable t, MonadConc m) => (a -> m b) -> t a -> m (t b) mapConcurrently f = runConcurrently . traverse (Concurrently . f) @@ -532,5 +652,33 @@ -- -- > pages <- forConcurrently ["url1", "url2", "url3"] $ \url -> getURL url --+-- @since 1.1.1.0 forConcurrently :: (Traversable t, MonadConc m) => t a -> (a -> m b)-> m (t b) forConcurrently = flip mapConcurrently++-- | 'mapConcurrently_' is 'mapConcurrently' with the return value+-- discarded, just like 'mapM_'.+--+-- @since 1.1.2.0+mapConcurrently_ :: (Foldable f, MonadConc m) => (a -> m b) -> f a -> m ()+mapConcurrently_ f = runConcurrently . foldMap (Concurrently . void . f)++-- | 'forConcurrently_' is 'forConcurrently' with the return value+-- discarded, just like 'forM_'.+--+-- @since 1.1.2.0+forConcurrently_ :: (Foldable f, MonadConc m) => f a -> (a -> m b) -> m ()+forConcurrently_ = flip mapConcurrently_++-- | Perform the action in the given number of threads.+--+-- @since 1.1.2.0+replicateConcurrently :: MonadConc m => Int -> m a -> m [a]+replicateConcurrently i = runConcurrently . sequenceA . replicate i . Concurrently++-- | 'replicateConcurrently_' is 'replicateConcurrently' with the+-- return values discarded.+--+-- @since 1.1.2.0+replicateConcurrently_ :: MonadConc m => Int -> m a -> m ()+replicateConcurrently_ i = void . replicateConcurrently i
Control/Concurrent/Classy/CRef.hs view
@@ -96,10 +96,14 @@ -- >readCRef ref >>= print -- -- To avoid this problem, use 'modifyCRef'' instead.+--+-- @since 1.0.0.0 modifyCRef :: MonadConc m => CRef m a -> (a -> a) -> m () modifyCRef ref f = readCRef ref >>= writeCRef ref . f  -- | Strict version of 'modifyCRef'+--+-- @since 1.0.0.0 modifyCRef' :: MonadConc m => CRef m a -> (a -> a) -> m () modifyCRef' ref f = do   x <- readCRef ref@@ -107,6 +111,8 @@  -- | Strict version of 'atomicModifyCRef'. This forces both the value -- stored in the @CRef@ as well as the value returned.+--+-- @since 1.0.0.0 atomicModifyCRef' :: MonadConc m => CRef m a -> (a -> (a,b)) -> m b atomicModifyCRef' ref f = do   b <- atomicModifyCRef ref $ \a -> case f a of
Control/Concurrent/Classy/Chan.hs view
@@ -33,6 +33,8 @@  -- | 'Chan' is an abstract type representing an unbounded FIFO -- channel.+--+-- @since 1.0.0.0 data Chan m a   = Chan (MVar m (Stream m a))          (MVar m (Stream m a)) -- Invariant: the Stream a is always an empty MVar@@ -42,6 +44,8 @@ data ChItem m a = ChItem a (Stream m a)  -- | Build and returns a new instance of 'Chan'.+--+-- @since 1.0.0.0 newChan :: MonadConc m => m (Chan m a) newChan = do   hole  <- newEmptyMVar@@ -50,6 +54,8 @@   pure (Chan readVar writeVar)  -- | Write a value to a 'Chan'.+--+-- @since 1.0.0.0 writeChan :: MonadConc m => Chan m a -> a -> m () writeChan (Chan _ writeVar) val = do   new_hole <- newEmptyMVar@@ -59,6 +65,8 @@     putMVar writeVar new_hole  -- | Read the next value from the 'Chan'.+--+-- @since 1.0.0.0 readChan :: MonadConc m => Chan m a -> m a readChan (Chan readVar _) =  modifyMVarMasked readVar $ \read_end -> do   (ChItem val new_read_end) <- readMVar read_end@@ -68,6 +76,8 @@ -- written to either channel from then on will be available from both. -- Hence this creates a kind of broadcast channel, where data written -- by anyone is seen by everyone else.+--+-- @since 1.0.0.0 dupChan :: MonadConc m => Chan m a -> m (Chan m a) dupChan (Chan _ writeVar) = do   hole       <- readMVar writeVar@@ -75,5 +85,7 @@   pure (Chan newReadVar writeVar)  -- | Write an entire list of items to a 'Chan'.+--+-- @since 1.0.0.0 writeList2Chan :: MonadConc m => Chan m a -> [a] -> m () writeList2Chan = mapM_ . writeChan
Control/Concurrent/Classy/MVar.hs view
@@ -54,6 +54,8 @@ -- | Swap the contents of a @MVar@, and return the value taken. This -- function is atomic only if there are no other producers fro this -- @MVar@.+--+-- @since 1.0.0.0 swapMVar :: MonadConc m => MVar m a -> a -> m a swapMVar cvar a = mask_ $ do   old <- takeMVar cvar@@ -61,6 +63,8 @@   return old  -- | Check if a @MVar@ is empty.+--+-- @since 1.0.0.0 isEmptyMVar :: MonadConc m => MVar m a -> m Bool isEmptyMVar cvar = do   val <- tryTakeMVar cvar@@ -72,6 +76,8 @@ -- finishing. This operation is exception-safe: it will replace the -- original contents of the @MVar@ if an exception is raised. However, -- it is only atomic if there are no other producers for this @MVar@.+--+-- @since 1.0.0.0 {-# INLINE withMVar #-} withMVar :: MonadConc m => MVar m a -> (a -> m b) -> m b withMVar cvar f = mask $ \restore -> do@@ -83,6 +89,8 @@  -- | Like 'withMVar', but the @IO@ action in the second argument is -- executed with asynchronous exceptions masked.+--+-- @since 1.0.0.0 {-# INLINE withMVarMasked #-} withMVarMasked :: MonadConc m => MVar m a -> (a -> m b) -> m b withMVarMasked cvar f = mask_ $ do@@ -97,12 +105,16 @@ -- the @MVar@ if an exception is raised during the operation. This -- function is only atomic if there are no other producers for this -- @MVar@.+--+-- @since 1.0.0.0 {-# INLINE modifyMVar_ #-} modifyMVar_ :: MonadConc m => MVar m a -> (a -> m a) -> m () modifyMVar_ cvar f = modifyMVar cvar $ fmap (\a -> (a,())) . f  -- | A slight variation on 'modifyMVar_' that allows a value to be -- returned (@b@) in addition to the modified value of the @MVar@.+--+-- @since 1.0.0.0 {-# INLINE modifyMVar #-} modifyMVar :: MonadConc m => MVar m a -> (a -> m (a, b)) -> m b modifyMVar cvar f = mask $ \restore -> do@@ -113,12 +125,16 @@  -- | Like 'modifyMVar_', but the @IO@ action in the second argument is -- executed with asynchronous exceptions masked.+--+-- @since 1.0.0.0 {-# INLINE modifyMVarMasked_ #-} modifyMVarMasked_ :: MonadConc m => MVar m a -> (a -> m a) -> m () modifyMVarMasked_ cvar f = modifyMVarMasked cvar $ fmap (\a -> (a,())) . f  -- | Like 'modifyMVar', but the @IO@ action in the second argument is -- executed with asynchronous exceptions masked.+--+-- @since 1.0.0.0 {-# INLINE modifyMVarMasked #-} modifyMVarMasked :: MonadConc m => MVar m a -> (a -> m (a, b)) -> m b modifyMVarMasked cvar f = mask_ $ do
Control/Concurrent/Classy/QSem.hs view
@@ -27,19 +27,27 @@ -- > bracket_ qaitQSem signalSSem (...) -- -- is safe; it never loses a unit of the resource.+--+-- @since 1.0.0.0 newtype QSem m = QSem (QSemN m)  -- | Build a new 'QSem' with a supplied initial quantity. The initial -- quantity must be at least 0.+--+-- @since 1.0.0.0 newQSem :: MonadConc m => Int -> m (QSem m) newQSem initial   | initial < 0 = fail "newQSem: Initial quantity mus tbe non-negative."   | otherwise   = QSem <$> newQSemN initial  -- | Wait for a unit to become available.+--+-- @since 1.0.0.0 waitQSem :: MonadConc m => QSem m -> m () waitQSem (QSem qSemN) = waitQSemN qSemN 1  -- | Signal that a unit of the 'QSem' is available.+--+-- @since 1.0.0.0 signalQSem :: MonadConc m => QSem m -> m () signalQSem (QSem qSemN) = signalQSemN qSemN 1
Control/Concurrent/Classy/QSemN.hs view
@@ -30,16 +30,22 @@ -- > bracket_ (waitQSemN n) (signalQSemN n) (...) -- -- is safe; it never loses any of the resource.+--+-- @since 1.0.0.0 newtype QSemN m = QSemN (MVar m (Int, [(Int, MVar m ())], [(Int, MVar m ())]))  -- | Build a new 'QSemN' with a supplied initial quantity. --  The initial quantity must be at least 0.+--+-- @since 1.0.0.0 newQSemN :: MonadConc m => Int -> m (QSemN m) newQSemN initial   | initial < 0 = fail "newQSemN: Initial quantity must be non-negative"   | otherwise   = QSemN <$> newMVar (initial, [], [])  -- | Wait for the specified quantity to become available+--+-- @since 1.0.0.0 waitQSemN :: MonadConc m => QSemN m -> Int -> m () waitQSemN (QSemN m) sz = mask_ $ do   (quantity, b1, b2) <- takeMVar m@@ -64,6 +70,8 @@       putMVar m r')  -- | Signal that a given quantity is now available from the 'QSemN'.+--+-- @since 1.0.0.0 signalQSemN :: MonadConc m => QSemN m -> Int -> m () signalQSemN (QSemN m) sz = uninterruptibleMask_ $ do   r  <- takeMVar m
Control/Concurrent/Classy/STM/TArray.hs view
@@ -28,8 +28,11 @@ -- It is currently implemented as @Array ix (TVar stm e)@, but it may -- be replaced by a more efficient implementation in the future (the -- interface will remain the same, however).+--+-- @since 1.0.0.0 newtype TArray stm i e = TArray (Array i (TVar stm e)) +-- | @since 1.0.0.0 instance MonadSTM stm => MArray (TArray stm) e stm where   getBounds (TArray a) = pure (bounds a) 
Control/Concurrent/Classy/STM/TBQueue.hs view
@@ -37,6 +37,8 @@  -- | 'TBQueue' is an abstract type representing a bounded FIFO -- channel.+--+-- @since 1.0.0.0 data TBQueue stm a    = TBQueue (TVar stm Int)              (TVar stm [a])@@ -44,6 +46,8 @@              (TVar stm [a])  -- | Build and returns a new instance of 'TBQueue'+--+-- @since 1.0.0.0 newTBQueue :: MonadSTM stm   => Int   -- ^ maximum number of elements the queue can hold   -> stm (TBQueue stm a)@@ -55,6 +59,8 @@   pure (TBQueue rsize readT wsize writeT)  -- | Write a value to a 'TBQueue'; retries if the queue is full.+--+-- @since 1.0.0.0 writeTBQueue :: MonadSTM stm => TBQueue stm a -> a -> stm () writeTBQueue (TBQueue rsize _ wsize writeT) a = do   w <- readTVar wsize@@ -71,6 +77,8 @@   writeTVar writeT (a:listend)  -- | Read the next value from the 'TBQueue'.+--+-- @since 1.0.0.0 readTBQueue :: MonadSTM stm => TBQueue stm a -> stm a readTBQueue (TBQueue rsize readT _ writeT) = do   xs <- readTVar readT@@ -92,11 +100,15 @@  -- | A version of 'readTBQueue' which does not retry. Instead it -- returns @Nothing@ if no value is available.+--+-- @since 1.0.0.0 tryReadTBQueue :: MonadSTM stm => TBQueue stm a -> stm (Maybe a) tryReadTBQueue c = (Just <$> readTBQueue c) `orElse` pure Nothing  -- | Get the next value from the @TBQueue@ without removing it, -- retrying if the channel is empty.+--+-- @since 1.0.0.0 peekTBQueue :: MonadSTM stm => TBQueue stm a -> stm a peekTBQueue c = do   x <- readTBQueue c@@ -105,6 +117,8 @@  -- | A version of 'peekTBQueue' which does not retry. Instead it -- returns @Nothing@ if no value is available.+--+-- @since 1.0.0.0 tryPeekTBQueue :: MonadSTM stm => TBQueue stm a -> stm (Maybe a) tryPeekTBQueue c = do   m <- tryReadTBQueue c@@ -116,6 +130,8 @@  -- | Put a data item back onto a channel, where it will be the next item read. -- Retries if the queue is full.+--+-- @since 1.0.0.0 unGetTBQueue :: MonadSTM stm => TBQueue stm a -> a -> stm () unGetTBQueue (TBQueue rsize readT wsize _) a = do   r <- readTVar rsize@@ -130,6 +146,8 @@   writeTVar readT (a:xs)  -- | Returns 'True' if the supplied 'TBQueue' is empty.+--+-- @since 1.0.0.0 isEmptyTBQueue :: MonadSTM stm => TBQueue stm a -> stm Bool isEmptyTBQueue (TBQueue _ readT _ writeT) = do   xs <- readTVar readT@@ -138,6 +156,8 @@     [] -> null <$> readTVar writeT  -- | Returns 'True' if the supplied 'TBQueue' is full.+--+-- @since 1.0.0.0 isFullTBQueue :: MonadSTM stm => TBQueue stm a -> stm Bool isFullTBQueue (TBQueue rsize _ wsize _) = do   w <- readTVar wsize
Control/Concurrent/Classy/STM/TChan.hs view
@@ -36,6 +36,8 @@  -- | 'TChan' is an abstract type representing an unbounded FIFO -- channel.+--+-- @since 1.0.0.0 data TChan stm a = TChan (TVar stm (TVarList stm a))                          (TVar stm (TVarList stm a)) @@ -43,6 +45,8 @@ data TList stm a = TNil | TCons a (TVarList stm a)  -- |Build and return a new instance of 'TChan'+--+-- @since 1.0.0.0 newTChan :: MonadSTM stm => stm (TChan stm a) newTChan = do   hole   <- newTVar TNil@@ -53,6 +57,8 @@ -- | Create a write-only 'TChan'.  More precisely, 'readTChan' will 'retry' -- even after items have been written to the channel.  The only way to -- read a broadcast channel is to duplicate it with 'dupTChan'.+--+-- @since 1.0.0.0 newBroadcastTChan :: MonadSTM stm => stm (TChan stm a) newBroadcastTChan = do     hole   <- newTVar TNil@@ -61,6 +67,8 @@     pure (TChan readT writeT)  -- | Write a value to a 'TChan'.+--+-- @since 1.0.0.0 writeTChan :: MonadSTM stm => TChan stm a -> a -> stm () writeTChan (TChan _ writeT) a = do   listend  <- readTVar writeT@@ -69,11 +77,15 @@   writeTVar writeT listend'  -- | Read the next value from the 'TChan'.+--+-- @since 1.0.0.0 readTChan :: MonadSTM stm => TChan stm a -> stm a readTChan tchan = tryReadTChan tchan >>= maybe retry pure  -- | A version of 'readTChan' which does not retry. Instead it -- returns @Nothing@ if no value is available.+--+-- @since 1.0.0.0 tryReadTChan :: MonadSTM stm => TChan stm a -> stm (Maybe a) tryReadTChan (TChan readT _) = do   listhead <- readTVar readT@@ -86,11 +98,15 @@  -- | Get the next value from the 'TChan' without removing it, -- retrying if the channel is empty.+--+-- @since 1.0.0.0 peekTChan :: MonadSTM stm => TChan stm a -> stm a peekTChan tchan = tryPeekTChan tchan >>= maybe retry pure  -- | A version of 'peekTChan' which does not retry. Instead it -- returns @Nothing@ if no value is available.+--+-- @since 1.0.0.0 tryPeekTChan :: MonadSTM stm => TChan stm a -> stm (Maybe a) tryPeekTChan (TChan readT _) = do   listhead <- readTVar readT@@ -103,6 +119,8 @@ -- either channel from then on will be available from both.  Hence -- this creates a kind of broadcast channel, where data written by -- anyone is seen by everyone else.+--+-- @since 1.0.0.0 dupTChan :: MonadSTM stm => TChan stm a -> stm (TChan stm a) dupTChan (TChan _ writeT) = do   hole   <- readTVar writeT@@ -111,6 +129,8 @@  -- | Put a data item back onto a channel, where it will be the next -- item read.+--+-- @since 1.0.0.0 unGetTChan :: MonadSTM stm => TChan stm a -> a -> stm () unGetTChan (TChan readT _) a = do    listhead <- readTVar readT@@ -118,6 +138,8 @@    writeTVar readT head'  -- | Returns 'True' if the supplied 'TChan' is empty.+--+-- @since 1.0.0.0 isEmptyTChan :: MonadSTM stm => TChan stm a -> stm Bool isEmptyTChan (TChan readT _) = do   listhead <- readTVar readT@@ -128,6 +150,8 @@  -- | Clone a 'TChan': similar to 'dupTChan', but the cloned channel starts with the -- same content available as the original channel.+--+-- @since 1.0.0.0 cloneTChan :: MonadSTM stm => TChan stm a -> stm (TChan stm a) cloneTChan (TChan readT writeT) = do   readpos <- readTVar readT
Control/Concurrent/Classy/STM/TMVar.hs view
@@ -36,9 +36,13 @@ -- | A @TMVar@ is like an @MVar@ or a @mVar@, but using transactional -- memory. As transactions are atomic, this makes dealing with -- multiple @TMVar@s easier than wrangling multiple @mVar@s.+--+-- @since 1.0.0.0 newtype TMVar stm a = TMVar (TVar stm (Maybe a))  -- | Create a 'TMVar' containing the given value.+--+-- @since 1.0.0.0 newTMVar :: MonadSTM stm => a -> stm (TMVar stm a) newTMVar = newTMVarN "" @@ -47,6 +51,8 @@ -- -- Name conflicts are handled as usual for 'TVar's. The name is -- prefixed with \"ctmvar-\".+--+-- @since 1.0.0.0 newTMVarN :: MonadSTM stm => String -> a -> stm (TMVar stm a) newTMVarN n a = do   let n' = if null n then "ctmvar" else "ctmvar-" ++ n@@ -54,6 +60,8 @@   return $ TMVar ctvar  -- | Create a new empty 'TMVar'.+--+-- @since 1.0.0.0 newEmptyTMVar :: MonadSTM stm => stm (TMVar stm a) newEmptyTMVar = newEmptyTMVarN "" @@ -61,6 +69,8 @@ -- -- Name conflicts are handled as usual for 'TVar's. The name is -- prefixed with \"ctmvar-\".+--+-- @since 1.0.0.0 newEmptyTMVarN :: MonadSTM stm => String -> stm (TMVar stm a) newEmptyTMVarN n = do   let n' = if null n then "ctmvar" else "ctmvar-" ++ n@@ -68,18 +78,24 @@   return $ TMVar ctvar  -- | Take the contents of a 'TMVar', or 'retry' if it is empty.+--+-- @since 1.0.0.0 takeTMVar :: MonadSTM stm => TMVar stm a -> stm a takeTMVar ctmvar = do   taken <- tryTakeTMVar ctmvar   maybe retry return taken  -- | Write to a 'TMVar', or 'retry' if it is full.+--+-- @since 1.0.0.0 putTMVar :: MonadSTM stm => TMVar stm a -> a -> stm () putTMVar ctmvar a = do   putted <- tryPutTMVar ctmvar a   unless putted retry  -- | Read from a 'TMVar' without emptying, or 'retry' if it is empty.+--+-- @since 1.0.0.0 readTMVar :: MonadSTM stm => TMVar stm a -> stm a readTMVar ctmvar = do   readed <- tryReadTMVar ctmvar@@ -87,6 +103,8 @@  -- | Try to take the contents of a 'TMVar', returning 'Nothing' if it -- is empty.+--+-- @since 1.0.0.0 tryTakeTMVar :: MonadSTM stm => TMVar stm a -> stm (Maybe a) tryTakeTMVar (TMVar ctvar) = do   val <- readTVar ctvar@@ -94,6 +112,8 @@   return val  -- | Try to write to a 'TMVar', returning 'False' if it is full.+--+-- @since 1.0.0.0 tryPutTMVar :: MonadSTM stm => TMVar stm a -> a -> stm Bool tryPutTMVar (TMVar ctvar) a = do   val <- readTVar ctvar@@ -102,15 +122,21 @@  -- | Try to read from a 'TMVar' without emptying, returning 'Nothing' -- if it is empty.+--+-- @since 1.0.0.0 tryReadTMVar :: MonadSTM stm => TMVar stm a -> stm (Maybe a) tryReadTMVar (TMVar ctvar) = readTVar ctvar  -- | Check if a 'TMVar' is empty or not.+--+-- @since 1.0.0.0 isEmptyTMVar :: MonadSTM stm => TMVar stm a -> stm Bool isEmptyTMVar ctmvar = isNothing `liftM` tryReadTMVar ctmvar  -- | Swap the contents of a 'TMVar' returning the old contents, or -- 'retry' if it is empty.+--+-- @since 1.0.0.0 swapTMVar :: MonadSTM stm => TMVar stm a -> a -> stm a swapTMVar ctmvar a = do   val <- takeTMVar ctmvar
Control/Concurrent/Classy/STM/TQueue.hs view
@@ -39,10 +39,14 @@ import Control.Monad.STM.Class  -- | 'TQueue' is an abstract type representing an unbounded FIFO channel.+--+-- @since 1.0.0.0 data TQueue stm a = TQueue (TVar stm [a])                            (TVar stm [a])  -- | Build and returns a new instance of 'TQueue'+--+-- @since 1.0.0.0 newTQueue :: MonadSTM stm => stm (TQueue stm a) newTQueue = do   readT  <- newTVar []@@ -50,12 +54,16 @@   pure (TQueue readT writeT)  -- | Write a value to a 'TQueue'.+--+-- @since 1.0.0.0 writeTQueue :: MonadSTM stm => TQueue stm a -> a -> stm () writeTQueue (TQueue _ writeT) a = do   listend <- readTVar writeT   writeTVar writeT (a:listend)  -- | Read the next value from the 'TQueue'.+--+-- @since 1.0.0.0 readTQueue :: MonadSTM stm => TQueue stm a -> stm a readTQueue (TQueue readT writeT) = do   xs <- readTVar readT@@ -76,11 +84,15 @@  -- | A version of 'readTQueue' which does not retry. Instead it -- returns @Nothing@ if no value is available.+--+-- @since 1.0.0.0 tryReadTQueue :: MonadSTM stm => TQueue stm a -> stm (Maybe a) tryReadTQueue c = (Just <$> readTQueue c) `orElse` pure Nothing  -- | Get the next value from the @TQueue@ without removing it, -- retrying if the channel is empty.+--+-- @since 1.0.0.0 peekTQueue :: MonadSTM stm => TQueue stm a -> stm a peekTQueue c = do   x <- readTQueue c@@ -89,6 +101,8 @@  -- | A version of 'peekTQueue' which does not retry. Instead it -- returns @Nothing@ if no value is available.+--+-- @since 1.0.0.0 tryPeekTQueue :: MonadSTM stm => TQueue stm a -> stm (Maybe a) tryPeekTQueue c = do   m <- tryReadTQueue c@@ -99,12 +113,16 @@       pure m  -- |Put a data item back onto a channel, where it will be the next item read.+--+-- @since 1.0.0.0 unGetTQueue :: MonadSTM stm => TQueue stm a -> a -> stm () unGetTQueue (TQueue readT _) a = do   xs <- readTVar readT   writeTVar readT (a:xs)  -- |Returns 'True' if the supplied 'TQueue' is empty.+--+-- @since 1.0.0.0 isEmptyTQueue :: MonadSTM stm => TQueue stm a -> stm Bool isEmptyTQueue (TQueue readT writeT) = do   xs <- readTVar readT
Control/Concurrent/Classy/STM/TVar.hs view
@@ -32,18 +32,24 @@ -- * @TVar@s  -- | Mutate the contents of a 'TVar'. This is non-strict.+--+-- @since 1.0.0.0 modifyTVar :: MonadSTM stm => TVar stm a -> (a -> a) -> stm () modifyTVar ctvar f = do   a <- readTVar ctvar   writeTVar ctvar $ f a  -- | Mutate the contents of a 'TVar' strictly.+--+-- @since 1.0.0.0 modifyTVar' :: MonadSTM stm => TVar stm a -> (a -> a) -> stm () modifyTVar' ctvar f = do   a <- readTVar ctvar   writeTVar ctvar $! f a  -- | Swap the contents of a 'TVar', returning the old value.+--+-- @since 1.0.0.0 swapTVar :: MonadSTM stm => TVar stm a -> a -> stm a swapTVar ctvar a = do   old <- readTVar ctvar@@ -53,6 +59,8 @@ -- | Set the value of returned 'TVar' to @True@ after a given number -- of microseconds. The caveats associated with 'threadDelay' also -- apply.+--+-- @since 1.0.0.0 registerDelay :: MonadConc m => Int -> m (TVar (STM m) Bool) registerDelay delay = do   var <- atomically (newTVar False)
Control/Monad/Conc/Class.hs view
@@ -50,7 +50,9 @@   , throw   , catch   , mask+  , Ca.mask_   , uninterruptibleMask+  , Ca.uninterruptibleMask_    -- * Mutable State   , newMVar@@ -98,6 +100,8 @@ -- -- Every @MonadConc@ has an associated 'MonadSTM', transactions of -- which can be run atomically.+--+-- @since 1.0.0.0 class ( Applicative m, Monad m       , MonadCatch m, MonadThrow m, MonadMask m       , MonadSTM (STM m)@@ -129,31 +133,43 @@     #-}    -- | The associated 'MonadSTM' for this class.+  --+  -- @since 1.0.0.0   type STM m :: * -> *    -- | The mutable reference type, like 'MVar's. This may contain one   -- value at a time, attempting to read or take from an \"empty\"   -- @MVar@ will block until it is full, and attempting to put to a   -- \"full\" @MVar@ will block until it is empty.+  --+  -- @since 1.0.0.0   type MVar m :: * -> *    -- | The mutable non-blocking reference type. These may suffer from   -- relaxed memory effects if functions outside the set @newCRef@,   -- @readCRef@, @atomicModifyCRef@, and @atomicWriteCRef@ are used.+  --+  -- @since 1.0.0.0   type CRef m :: * -> *    -- | When performing compare-and-swap operations on @CRef@s, a   -- @Ticket@ is a proof that a thread observed a specific previous   -- value.+  --+  -- @since 1.0.0.0   type Ticket m :: * -> *    -- | An abstract handle to a thread.+  --+  -- @since 1.0.0.0   type ThreadId m :: *    -- | Fork a computation to happen concurrently. Communication may   -- happen over @MVar@s.   --   -- > fork ma = forkWithUnmask (\_ -> ma)+  --+  -- @since 1.0.0.0   fork :: m () -> m (ThreadId m)   fork ma = forkWithUnmask (\_ -> ma) @@ -162,6 +178,8 @@   -- not be used within a 'mask' or 'uninterruptibleMask'.   --   -- > forkWithUnmask = forkWithUnmaskN ""+  --+  -- @since 1.0.0.0   forkWithUnmask :: ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)   forkWithUnmask = forkWithUnmaskN "" @@ -173,6 +191,8 @@   -- numeric suffix, counting up from 1.   --   -- > forkWithUnmaskN _ = forkWithUnmask+  --+  -- @since 1.0.0.0   forkWithUnmaskN :: String -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)   forkWithUnmaskN _ = forkWithUnmask @@ -183,6 +203,8 @@   -- total number of capabilities as returned by 'getNumCapabilities'.   --   -- > forkOn c ma = forkOnWithUnmask c (\_ -> ma)+  --+  -- @since 1.0.0.0   forkOn :: Int -> m () -> m (ThreadId m)   forkOn c ma = forkOnWithUnmask c (\_ -> ma) @@ -190,6 +212,8 @@   -- given CPU, as with 'forkOn'.   --   -- > forkOnWithUnmask = forkOnWithUnmaskN ""+  --+  -- @since 1.0.0.0   forkOnWithUnmask :: Int -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)   forkOnWithUnmask = forkOnWithUnmaskN "" @@ -197,20 +221,30 @@   -- given CPU, as with 'forkOn'.   --   -- > forkOnWithUnmaskN _ = forkOnWithUnmask+  --+  -- @since 1.0.0.0   forkOnWithUnmaskN :: String -> Int -> ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)   forkOnWithUnmaskN _ = forkOnWithUnmask    -- | Get the number of Haskell threads that can run simultaneously.+  --+  -- @since 1.0.0.0   getNumCapabilities :: m Int    -- | Set the number of Haskell threads that can run simultaneously.+  --+  -- @since 1.0.0.0   setNumCapabilities :: Int -> m ()    -- | Get the @ThreadId@ of the current thread.+  --+  -- @since 1.0.0.0   myThreadId :: m (ThreadId m)    -- | Allows a context-switch to any other currently runnable thread   -- (if any).+  --+  -- @since 1.0.0.0   yield :: m ()    -- | Yields the current thread, and optionally suspends the current@@ -221,12 +255,16 @@   -- will never continue to run earlier than specified.   --   -- > threadDelay _ = yield+  --+  -- @since 1.0.0.0   threadDelay :: Int -> m ()   threadDelay _ = yield    -- | Create a new empty @MVar@.   --   -- > newEmptyMVar = newEmptyMVarN ""+  --+  -- @since 1.0.0.0   newEmptyMVar :: m (MVar m a)   newEmptyMVar = newEmptyMVarN "" @@ -238,43 +276,59 @@   -- numeric suffix, counting up from 1.   --   -- > newEmptyMVarN _ = newEmptyMVar+  --+  -- @since 1.0.0.0   newEmptyMVarN :: String -> m (MVar m a)   newEmptyMVarN _ = newEmptyMVar    -- | Put a value into a @MVar@. If there is already a value there,   -- this will block until that value has been taken, at which point   -- the value will be stored.+  --+  -- @since 1.0.0.0   putMVar :: MVar m a -> a -> m ()    -- | Attempt to put a value in a @MVar@ non-blockingly, returning   -- 'True' (and filling the @MVar@) if there was nothing there,   -- otherwise returning 'False'.+  --+  -- @since 1.0.0.0   tryPutMVar :: MVar m a -> a -> m Bool    -- | Block until a value is present in the @MVar@, and then return   -- it. This does not \"remove\" the value, multiple reads are   -- possible.+  --+  -- @since 1.0.0.0   readMVar :: MVar m a -> m a    -- | Attempt to read a value from a @MVar@ non-blockingly, returning   -- a 'Just' (and emptying the @MVar@) if there is something there,   -- otherwise returning 'Nothing'. As with 'readMVar', this does not   -- \"remove\" the value.+  --+  -- @since 1.1.0.0   tryReadMVar :: MVar m a -> m (Maybe a)    -- | Take a value from a @MVar@. This \"empties\" the @MVar@,   -- allowing a new value to be put in. This will block if there is no   -- value in the @MVar@ already, until one has been put.+  --+  -- @since 1.0.0.0   takeMVar :: MVar m a -> m a    -- | Attempt to take a value from a @MVar@ non-blockingly, returning   -- a 'Just' (and emptying the @MVar@) if there was something there,   -- otherwise returning 'Nothing'.+  --+  -- @since 1.0.0.0   tryTakeMVar :: MVar m a -> m (Maybe a)    -- | Create a new reference.   --   -- > newCRef = newCRefN ""+  --+  -- @since 1.0.0.0   newCRef :: a -> m (CRef m a)   newCRef = newCRefN "" @@ -286,37 +340,51 @@   -- numeric suffix, counting up from 1.   --   -- > newCRefN _ = newCRef+  --+  -- @since 1.0.0.0   newCRefN :: String -> a -> m (CRef m a)   newCRefN _ = newCRef    -- | Read the current value stored in a reference.   --   -- > readCRef cref = readForCAS cref >>= peekTicket+  --+  -- @since 1.0.0.0   readCRef :: CRef m a -> m a   readCRef cref = readForCAS cref >>= peekTicket    -- | Atomically modify the value stored in a reference. This imposes   -- a full memory barrier.+  --+  -- @since 1.0.0.0   atomicModifyCRef :: CRef m a -> (a -> (a, b)) -> m b    -- | Write a new value into an @CRef@, without imposing a memory   -- barrier. This means that relaxed memory effects can be observed.+  --+  -- @since 1.0.0.0   writeCRef :: CRef m a -> a -> m ()    -- | Replace the value stored in a reference, with the   -- barrier-to-reordering property that 'atomicModifyCRef' has.   --   -- > atomicWriteCRef r a = atomicModifyCRef r $ const (a, ())+  --+  -- @since 1.0.0.0   atomicWriteCRef :: CRef m a -> a -> m ()   atomicWriteCRef r a = atomicModifyCRef r $ const (a, ())    -- | Read the current value stored in a reference, returning a   -- @Ticket@, for use in future compare-and-swap operations.+  --+  -- @since 1.0.0.0   readForCAS :: CRef m a -> m (Ticket m a)    -- | Extract the actual Haskell value from a @Ticket@.   --   -- The @proxy m@ is to determine the @m@ in the @Ticket@ type.+  --+  -- @since 1.0.0.0   peekTicket' :: proxy m -> Ticket m a -> a    -- | Perform a machine-level compare-and-swap (CAS) operation on a@@ -324,32 +392,44 @@   -- most current value in the @CRef@.   --   -- This is strict in the \"new\" value argument.+  --+  -- @since 1.0.0.0   casCRef :: CRef m a -> Ticket m a -> a -> m (Bool, Ticket m a)    -- | A replacement for 'atomicModifyCRef' using a compare-and-swap.   --   -- This is strict in the \"new\" value argument.+  --+  -- @since 1.0.0.0   modifyCRefCAS :: CRef m a -> (a -> (a, b)) -> m b    -- | A variant of 'modifyCRefCAS' which doesn't return a result.   --   -- > modifyCRefCAS_ cref f = modifyCRefCAS cref (\a -> (f a, ()))+  --+  -- @since 1.0.0.0   modifyCRefCAS_ :: CRef m a -> (a -> a) -> m ()   modifyCRefCAS_ cref f = modifyCRefCAS cref (\a -> (f a, ()))    -- | Perform an STM transaction atomically.+  --+  -- @since 1.0.0.0   atomically :: STM m a -> m a    -- | Read the current value stored in a @TVar@. This may be   -- implemented differently for speed.   --   -- > readTVarConc = atomically . readTVar+  --+  -- @since 1.0.0.0   readTVarConc :: TVar (STM m) a -> m a   readTVarConc = atomically . readTVar    -- | Throw an exception to the target thread. This blocks until the   -- exception is delivered, and it is just as if the target thread   -- had raised it with 'throw'. This can interrupt a blocked action.+  --+  -- @since 1.0.0.0   throwTo :: Exception e => ThreadId m -> e -> m ()  -------------------------------------------------------------------------------@@ -359,6 +439,8 @@  -- | Create a concurrent computation for the provided action, and -- return a @MVar@ which can be used to query the result.+--+-- @since 1.0.0.0 spawn :: MonadConc m => m a -> m (MVar m a) spawn ma = do   cvar <- newEmptyMVar@@ -371,6 +453,8 @@ -- -- This function is useful for informing the parent when a child -- terminates, for example.+--+-- @since 1.0.0.0 forkFinally :: MonadConc m => m a -> (Either SomeException a -> m ()) -> m (ThreadId m) forkFinally action and_then =   mask $ \restore ->@@ -379,6 +463,8 @@ -- | Raise the 'ThreadKilled' exception in the target thread. Note -- that if the thread is prepared to catch this exception, it won't -- actually kill it.+--+-- @since 1.0.0.0 killThread :: MonadConc m => ThreadId m -> m () killThread tid = throwTo tid ThreadKilled @@ -388,6 +474,8 @@ -- If no name is given, the @ThreadId@ is used. If names conflict, -- successive threads with the same name are given a numeric suffix, -- counting up from 1.+--+-- @since 1.0.0.0 forkN :: MonadConc m => String -> m () -> m (ThreadId m) forkN name ma = forkWithUnmaskN name (\_ -> ma) @@ -397,16 +485,22 @@ -- If no name is given, the @ThreadId@ is used. If names conflict, -- successive threads with the same name are given a numeric suffix, -- counting up from 1.+--+-- @since 1.0.0.0 forkOnN :: MonadConc m => String -> Int -> m () -> m (ThreadId m) forkOnN name i ma = forkOnWithUnmaskN name i (\_ -> ma)  -- Bound Threads  -- | Provided for compatibility, always returns 'False'.+--+-- @since 1.0.0.0 rtsSupportsBoundThreads :: Bool rtsSupportsBoundThreads = False  -- | Provided for compatibility, always returns 'False'.+--+-- @since 1.0.0.0 isCurrentThreadBound :: MonadConc m => m Bool isCurrentThreadBound = pure False @@ -415,6 +509,8 @@ -- | Throw an exception. This will \"bubble up\" looking for an -- exception handler capable of dealing with it and, if one is not -- found, the thread is killed.+--+-- @since 1.0.0.0 throw :: (MonadConc m, Exception e) => e -> m a throw = Ca.throwM @@ -422,6 +518,8 @@ -- exceptions raised by 'throw', unlike the more general -- Control.Exception.catch function. If you need to be able to catch -- /all/ errors, you will have to use 'IO'.+--+-- @since 1.0.0.0 catch :: (MonadConc m, Exception e) => m a -> (e -> m a) -> m a catch = Ca.catch @@ -435,6 +533,8 @@ -- prevailing masking state within the context of the masked -- computation. This function should not be used within an -- 'uninterruptibleMask'.+--+-- @since 1.0.0.0 mask :: MonadConc m => ((forall a. m a -> m a) -> m b) -> m b mask = Ca.mask @@ -448,12 +548,16 @@ -- interruptible operation will only block for a short period of -- time. The supplied unmasking function should not be used within a -- 'mask'.+--+-- @since 1.0.0.0 uninterruptibleMask :: MonadConc m => ((forall a. m a -> m a) -> m b) -> m b uninterruptibleMask = Ca.uninterruptibleMask  -- Mutable Variables  -- | Create a new @MVar@ containing a value.+--+-- @since 1.0.0.0 newMVar :: MonadConc m => a -> m (MVar m a) newMVar a = do   cvar <- newEmptyMVar@@ -466,6 +570,8 @@ -- If no name is given, a counter starting from 0 is used. If names -- conflict, successive @MVar@s with the same name are given a numeric -- suffix, counting up from 1.+--+-- @since 1.0.0.0 newMVarN :: MonadConc m => String -> a -> m (MVar m a) newMVarN n a = do   cvar <- newEmptyMVarN n@@ -476,11 +582,15 @@ -- -- This doesn't do do any monadic computation, the @m@ appears in the -- result type to determine the @m@ in the @Ticket@ type.+--+-- @since 1.0.0.0 peekTicket :: forall m a. MonadConc m => Ticket m a -> m a peekTicket t = pure $ peekTicket' (Proxy :: Proxy m) (t :: Ticket m a)  -- | Compare-and-swap a value in a @CRef@, returning an indication of -- success and the new value.+--+-- @since 1.0.0.0 cas :: MonadConc m => CRef m a -> a -> m (Bool, a) cas cref a = do   tick         <- readForCAS cref@@ -492,6 +602,7 @@ ------------------------------------------------------------------------------- -- Concrete instances +-- | @since 1.0.0.0 instance MonadConc IO where   type STM      IO = IO.STM   type MVar     IO = IO.MVar@@ -578,29 +689,47 @@  -- | New threads inherit the reader state of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(ReaderT r, MonadConc m, id) +-- | @since 1.0.0.0 INSTANCE(IdentityT, MonadConc m, id)  -- | New threads inherit the writer state of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(WL.WriterT w, (MonadConc m, Monoid w), fst)+ -- | New threads inherit the writer state of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(WS.WriterT w, (MonadConc m, Monoid w), fst)  -- | New threads inherit the state of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(SL.StateT s, MonadConc m, fst)+ -- | New threads inherit the state of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(SS.StateT s, MonadConc m, fst)  -- | New threads inherit the states of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(RL.RWST r w s, (MonadConc m, Monoid w), (\(a,_,_) -> a))+ -- | New threads inherit the states of their parent, but do not -- communicate results back.+--+-- @since 1.0.0.0 INSTANCE(RS.RWST r w s, (MonadConc m, Monoid w), (\(a,_,_) -> a))  #undef INSTANCE@@ -609,6 +738,8 @@  -- | Given a function to remove the transformer-specific state, lift -- a function invocation.+--+-- @since 1.0.0.0 liftedF :: (MonadTransControl t, MonadConc m)   => (forall x. StT t x -> x)   -> (m a -> m b)@@ -618,6 +749,8 @@  -- | Given a function to remove the transformer-specific state, lift -- a @fork(on)WithUnmask@ invocation.+--+-- @since 1.0.0.0 liftedFork :: (MonadTransControl t, MonadConc m)   => (forall x. StT t x -> x)   -> (((forall x. m x -> m x) -> m a) -> m b)
Control/Monad/STM/Class.hs view
@@ -52,6 +52,8 @@ -- This class does not provide any way to run transactions, rather -- each 'MonadConc' has an associated @MonadSTM@ from which it can -- atomically run a transaction.+--+-- @since 1.0.0.0 class Ca.MonadCatch stm => MonadSTM stm where   {-# MINIMAL         retry@@ -64,23 +66,31 @@   -- | The mutable reference type. These behave like 'TVar's, in that   -- they always contain a value and updates are non-blocking and   -- synchronised.+  --+  -- @since 1.0.0.0   type TVar stm :: * -> *    -- | Retry execution of this transaction because it has seen values   -- in @TVar@s that it shouldn't have. This will result in the   -- thread running the transaction being blocked until any @TVar@s   -- referenced in it have been mutated.+  --+  -- @since 1.0.0.0   retry :: stm a    -- | Run the first transaction and, if it @retry@s, run the second   -- instead. If the monad is an instance of   -- 'Alternative'/'MonadPlus', 'orElse' should be the '(<|>)'/'mplus'   -- function.+  --+  -- @since 1.0.0.0   orElse :: stm a -> stm a -> stm a    -- | Create a new @TVar@ containing the given value.   --   -- > newTVar = newTVarN ""+  --+  -- @since 1.0.0.0   newTVar :: a -> stm (TVar stm a)   newTVar = newTVarN "" @@ -93,28 +103,41 @@   -- a numeric suffix, counting up from 1.   --   -- > newTVarN _ = newTVar+  --+  -- @since 1.0.0.0   newTVarN :: String -> a -> stm (TVar stm a)   newTVarN _ = newTVar    -- | Return the current value stored in a @TVar@.+  --+  -- @since 1.0.0.0   readTVar :: TVar stm a -> stm a    -- | Write the supplied value into the @TVar@.+  --+  -- @since 1.0.0.0   writeTVar :: TVar stm a -> a -> stm ()  -- | Check whether a condition is true and, if not, call @retry@.+--+-- @since 1.0.0.0 check :: MonadSTM stm => Bool -> stm () check b = unless b retry  -- | Throw an exception. This aborts the transaction and propagates -- the exception.+--+-- @since 1.0.0.0 throwSTM :: (MonadSTM stm, Exception e) => e -> stm a throwSTM = Ca.throwM  -- | Handling exceptions from 'throwSTM'.+--+-- @since 1.0.0.0 catchSTM :: (MonadSTM stm, Exception e) => stm a -> (e -> stm a) -> stm a catchSTM = Ca.catch +-- | @since 1.0.0.0 instance MonadSTM STM.STM where   type TVar STM.STM = STM.TVar @@ -138,17 +161,28 @@   readTVar    = lift . readTVar     ; \   writeTVar v = lift . writeTVar v  } +-- | @since 1.0.0.0 INSTANCE(ReaderT r, MonadSTM stm, id) +-- | @since 1.0.0.0 INSTANCE(IdentityT, MonadSTM stm, id) +-- | @since 1.0.0.0 INSTANCE(WL.WriterT w, (MonadSTM stm, Monoid w), fst)++-- | @since 1.0.0.0 INSTANCE(WS.WriterT w, (MonadSTM stm, Monoid w), fst) +-- | @since 1.0.0.0 INSTANCE(SL.StateT s, MonadSTM stm, fst)++-- | @since 1.0.0.0 INSTANCE(SS.StateT s, MonadSTM stm, fst) +-- | @since 1.0.0.0 INSTANCE(RL.RWST r w s, (MonadSTM stm, Monoid w), (\(a,_,_) -> a))++-- | @since 1.0.0.0 INSTANCE(RS.RWST r w s, (MonadSTM stm, Monoid w), (\(a,_,_) -> a))  #undef INSTANCE@@ -157,6 +191,8 @@  -- | Given a function to remove the transformer-specific state, lift -- an @orElse@ invocation.+--+-- @since 1.0.0.0 liftedOrElse :: (MonadTransControl t, MonadSTM stm)   => (forall x. StT t x -> x)   -> t stm a -> t stm a -> t stm a
concurrency.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                concurrency-version:             1.1.1.0+version:             1.1.2.0 synopsis:            Typeclasses, functions, and data types for concurrency and STM.  description:@@ -84,7 +84,7 @@ source-repository this   type:     git   location: https://github.com/barrucadu/dejafu.git-  tag:      concurrency-1.1.1.0+  tag:      concurrency-1.1.2.0  library   exposed-modules:     Control.Monad.Conc.Class