async 2.0.2 → 2.1.0
raw patch · 3 files changed
+149/−62 lines, 3 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Control.Concurrent.Async: instance Alternative Concurrently
- Control.Concurrent.Async: instance Applicative Concurrently
- Control.Concurrent.Async: instance Eq (Async a)
- Control.Concurrent.Async: instance Functor Async
- Control.Concurrent.Async: instance Functor Concurrently
- Control.Concurrent.Async: instance Monad Concurrently
- Control.Concurrent.Async: instance Ord (Async a)
- Control.Concurrent.Async: runConcurrently :: Concurrently a -> IO a
+ Control.Concurrent.Async: [runConcurrently] :: Concurrently a -> IO a
+ Control.Concurrent.Async: forConcurrently :: Traversable t => t a -> (a -> IO b) -> IO (t b)
+ Control.Concurrent.Async: instance GHC.Base.Alternative Control.Concurrent.Async.Concurrently
+ Control.Concurrent.Async: instance GHC.Base.Applicative Control.Concurrent.Async.Concurrently
+ Control.Concurrent.Async: instance GHC.Base.Functor Control.Concurrent.Async.Async
+ Control.Concurrent.Async: instance GHC.Base.Functor Control.Concurrent.Async.Concurrently
+ Control.Concurrent.Async: instance GHC.Base.Monoid a => GHC.Base.Monoid (Control.Concurrent.Async.Concurrently a)
+ Control.Concurrent.Async: instance GHC.Classes.Eq (Control.Concurrent.Async.Async a)
+ Control.Concurrent.Async: instance GHC.Classes.Ord (Control.Concurrent.Async.Async a)
+ Control.Concurrent.Async: waitAnyCatchSTM :: [Async a] -> STM (Async a, Either SomeException a)
+ Control.Concurrent.Async: waitAnySTM :: [Async a] -> STM (Async a, a)
+ Control.Concurrent.Async: waitBothSTM :: Async a -> Async b -> STM (a, b)
+ Control.Concurrent.Async: waitEitherCatchSTM :: Async a -> Async b -> STM (Either (Either SomeException a) (Either SomeException b))
+ Control.Concurrent.Async: waitEitherSTM :: Async a -> Async b -> STM (Either a b)
+ Control.Concurrent.Async: waitEitherSTM_ :: Async a -> Async b -> STM ()
Files
- Control/Concurrent/Async.hs +92/−18
- async.cabal +12/−44
- changelog.md +45/−0
Control/Concurrent/Async.hs view
@@ -105,11 +105,17 @@ waitEither_, waitBoth, + -- ** Waiting for multiple 'Async's in STM+ waitAnySTM, waitAnyCatchSTM,+ waitEitherSTM, waitEitherCatchSTM,+ waitEitherSTM_,+ waitBothSTM,+ -- ** Linking link, link2, -- * Convenient utilities- race, race_, concurrently, mapConcurrently,+ race, race_, concurrently, mapConcurrently, forConcurrently, Concurrently(..), ) where@@ -122,8 +128,15 @@ #endif import Control.Monad import Control.Applicative+#if !MIN_VERSION_base(4,8,0)+import Data.Monoid (Monoid(mempty,mappend)) import Data.Traversable+#endif+#if MIN_VERSION_base(4,9,0)+import Data.Semigroup (Semigroup((<>)))+#endif + import GHC.Exts import GHC.IO hiding (finally, onException) import GHC.Conc@@ -316,9 +329,15 @@ -- If multiple 'Async's complete or have completed, then the value -- returned corresponds to the first completed 'Async' in the list. --+{-# INLINE waitAnyCatch #-} waitAnyCatch :: [Async a] -> IO (Async a, Either SomeException a)-waitAnyCatch asyncs =- atomically $+waitAnyCatch = atomically . waitAnyCatchSTM++-- | A version of 'waitAnyCatch' that can be used inside an STM transaction.+--+-- @since 2.1.0+waitAnyCatchSTM :: [Async a] -> STM (Async a, Either SomeException a)+waitAnyCatchSTM asyncs = foldr orElse retry $ map (\a -> do r <- waitCatchSTM a; return (a, r)) asyncs @@ -336,9 +355,15 @@ -- If multiple 'Async's complete or have completed, then the value -- returned corresponds to the first completed 'Async' in the list. --+{-# INLINE waitAny #-} waitAny :: [Async a] -> IO (Async a, a)-waitAny asyncs =- atomically $+waitAny = atomically . waitAnySTM++-- | A version of 'waitAny' that can be used inside an STM transaction.+--+-- @since 2.1.0+waitAnySTM :: [Async a] -> STM (Async a, a)+waitAnySTM asyncs = foldr orElse retry $ map (\a -> do r <- waitSTM a; return (a, r)) asyncs @@ -350,11 +375,19 @@ waitAny asyncs `finally` mapM_ cancel asyncs -- | Wait for the first of two @Async@s to finish.+{-# INLINE waitEitherCatch #-} waitEitherCatch :: Async a -> Async b -> IO (Either (Either SomeException a) (Either SomeException b))-waitEitherCatch left right =- atomically $+waitEitherCatch left right = atomically (waitEitherCatchSTM left right)++-- | A version of 'waitEitherCatch' that can be used inside an STM transaction.+--+-- @since 2.1.0+waitEitherCatchSTM :: Async a -> Async b+ -> STM (Either (Either SomeException a)+ (Either SomeException b))+waitEitherCatchSTM left right = (Left <$> waitCatchSTM left) `orElse` (Right <$> waitCatchSTM right)@@ -372,18 +405,30 @@ -- that finished first raised an exception, then the exception is -- re-thrown by 'waitEither'. --+{-# INLINE waitEither #-} waitEither :: Async a -> Async b -> IO (Either a b)-waitEither left right =- atomically $+waitEither left right = atomically (waitEitherSTM left right)++-- | A version of 'waitEither' that can be used inside an STM transaction.+--+-- @since 2.1.0+waitEitherSTM :: Async a -> Async b -> STM (Either a b)+waitEitherSTM left right = (Left <$> waitSTM left) `orElse` (Right <$> waitSTM right) -- | Like 'waitEither', but the result is ignored. --+{-# INLINE waitEither_ #-} waitEither_ :: Async a -> Async b -> IO ()-waitEither_ left right =- atomically $+waitEither_ left right = atomically (waitEitherSTM_ left right)++-- | A version of 'waitEither_' that can be used inside an STM transaction.+--+-- @since 2.1.0+waitEitherSTM_:: Async a -> Async b -> STM ()+waitEitherSTM_ left right = (void $ waitSTM left) `orElse` (void $ waitSTM right)@@ -399,9 +444,15 @@ -- an exception before they have both finished, then the exception is -- re-thrown by 'waitBoth'. --+{-# INLINE waitBoth #-} waitBoth :: Async a -> Async b -> IO (a,b)-waitBoth left right =- atomically $ do+waitBoth left right = atomically (waitBothSTM left right)++-- | A version of 'waitBoth' that can be used inside an STM transaction.+--+-- @since 2.1.0+waitBothSTM :: Async a -> Async b -> STM (a,b)+waitBothSTM left right = do a <- waitSTM left `orElse` (waitSTM right >> retry)@@ -519,7 +570,9 @@ `catchAll` (putMVar done . Left) rid <- forkIO $ restore (right >>= putMVar done . Right . Right) `catchAll` (putMVar done . Left)- let stop = killThread lid >> killThread rid+ let stop = killThread rid >> killThread lid+ -- kill right before left, to match the semantics of+ -- the version using withAsync. (#27) r <- restore (collect done) `onException` stop stop return r@@ -538,6 +591,14 @@ mapConcurrently :: Traversable t => (a -> IO b) -> t a -> IO (t b) mapConcurrently f = runConcurrently . traverse (Concurrently . f) +-- | `forConcurrently` is `mapConcurrently` with its arguments flipped+--+-- > pages <- forConcurrently ["url1", "url2", "url3"] $ \url -> getURL url+--+-- @since 2.1.0+forConcurrently :: Traversable t => t a -> (a -> IO b)-> IO (t b)+forConcurrently = flip mapConcurrently+ -- ----------------------------------------------------------------------------- -- | A value of type @Concurrently a@ is an @IO@ operation that can be@@ -571,10 +632,23 @@ Concurrently as <|> Concurrently bs = Concurrently $ either id id <$> race as bs -instance Monad Concurrently where- return = pure- Concurrently a >>= f =- Concurrently $ a >>= runConcurrently . f+#if MIN_VERSION_base(4,9,0)+-- | Only defined by @async@ for @base >= 4.9@+--+-- @since 2.1.0+instance Semigroup a => Semigroup (Concurrently a) where+ (<>) = liftA2 (<>)++-- | @since 2.1.0+instance (Semigroup a, Monoid a) => Monoid (Concurrently a) where+ mempty = pure mempty+ mappend = (<>)+#else+-- | @since 2.1.0+instance Monoid a => Monoid (Concurrently a) where+ mempty = pure mempty+ mappend = liftA2 mappend+#endif -- ----------------------------------------------------------------------------
async.cabal view
@@ -1,4 +1,6 @@ name: async+version: 2.1.0+-- don't forget to update ./changelog.md! synopsis: Run IO operations asynchronously and wait for their results description:@@ -21,47 +23,7 @@ * The API makes it possible to build a tree of threads that are automatically killed when their parent dies (see 'withAsync').- .- Changes in 2.0.2:- .- * Add a Monad instance for Concurrently- * Bump base dependency to allow 4.9- .- Changes in 2.0.1.6:- .- * Add workaround to waitCatch for #14- .- Changes in 2.0.1.5:- .- * Bump @base@ dependencies for GHC 7.8- .- Changes in 2.0.1.4:- .- * Bump @base@ dependency of test suite- .- Changes in 2.0.1.3:- .- * Bump @base@ dependency to allow 4.6- .- Changes in 2.0.1.2:- .- * Bump @stm@ dependency to 2.4- .- Changes in 2.0.1.1:- .- * Safe Haskell support: @Control.Concurrent.Async@ is now @Trustworthy@- .- Changes in 2.0.1.0:- .- * Added a @Functor@ instance for @Async@- .- * Added @asyncBound@, @asyncOn@, @asyncWithUnmask@, @asyncOnWithUnmask@, @withAsyncBound@, @withAsyncOn@, @withAsyncWithUnmask@, @withAsyncOnWithUnmask@.- .- * Added @mapConcurrently@- .- * Added @Concurrently@ (with @Applicative@ and @Alternative@ instances) -version: 2.0.2 license: BSD3 license-file: LICENSE author: Simon Marlow@@ -69,12 +31,13 @@ copyright: (c) Simon Marlow 2012 category: Concurrency build-type: Simple-cabal-version: >=1.8+cabal-version: >=1.10 homepage: https://github.com/simonmar/async bug-reports: https://github.com/simonmar/async/issues-tested-with: GHC==7.0.3, GHC==7.2.2, GHC==7.4.1+tested-with: GHC==7.11.*, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2, GHC==7.0.4 extra-source-files:+ changelog.md bench/race.hs source-repository head@@ -82,14 +45,19 @@ location: https://github.com/simonmar/async.git library+ default-language: Haskell2010+ other-extensions: CPP, MagicHash, RankNTypes, UnboxedTuples+ if impl(ghc>=7.1)+ other-extensions: Trustworthy exposed-modules: Control.Concurrent.Async- build-depends: base >= 4.3 && < 4.9, stm >= 2.2 && < 2.5+ build-depends: base >= 4.3 && < 4.10, stm >= 2.2 && < 2.5 test-suite test-async+ default-language: Haskell2010 type: exitcode-stdio-1.0 hs-source-dirs: test main-is: test-async.hs- build-depends: base >= 4.3 && < 4.9,+ build-depends: base >= 4.3 && < 4.10, async, test-framework, test-framework-hunit,
+ changelog.md view
@@ -0,0 +1,45 @@+## Changes in 2.1.0:++ - Bump base dependency to allow 4.10+ - Remove invalid Monad instance for `Concurrently`+ - Add `Monoid` and `Semigroup` instances for `Concurrently`+ - Add `forConcurrently` (flipped version of `mapConcurrently`)+ - Add STM version of all applicable IO functions:+ `waitAnySTM`, `waitAnyCatchSTM`, `waitEitherSTM`,+ `waitEitherCatchSTM`, `waitEitherSTM_`, and `waitBothSTM`.++## Changes in 2.0.2:++ - Add a Monad instance for `Concurrently`+ - Bump base dependency to allow 4.9++## Changes in 2.0.1.6:++ - Add workaround to waitCatch for #14++## Changes in 2.0.1.5:++ - Bump `base` dependencies for GHC 7.8++## Changes in 2.0.1.4:++ - Bump `base` dependency of test suite++## Changes in 2.0.1.3:++ - Bump `base` dependency to allow 4.6++## Changes in 2.0.1.2:++ - Bump `stm` dependency to 2.4++## Changes in 2.0.1.1:++ - Safe Haskell support: `Control.Concurrent.Async` is now `Trustworthy`++## Changes in 2.0.1.0:++ - Added a `Functor` instance for `Async`+ - Added `asyncBound`, `asyncOn`, `asyncWithUnmask`, `asyncOnWithUnmask`, `withAsyncBound`, `withAsyncOn`, `withAsyncWithUnmask`, `withAsyncOnWithUnmask`.+ - Added `mapConcurrently`+ - Added `Concurrently` (with `Applicative` and `Alternative` instances)