{-# LANGUAGE CPP, MagicHash, UnboxedTuples, RankNTypes, ExistentialQuantification #-} #if __GLASGOW_HASKELL__ >= 701 {-# LANGUAGE Trustworthy #-} #endif #if __GLASGOW_HASKELL__ < 710 {-# LANGUAGE DeriveDataTypeable #-} #endif {-# OPTIONS -Wall #-}------------------------------------------------------------------------------- |-- Module : Control.Concurrent.Async.Internal-- Copyright : (c) Simon Marlow 2012-- License : BSD3 (see the file LICENSE)---- Maintainer : Simon Marlow <marlowsd@gmail.com>-- Stability : provisional-- Portability : non-portable (requires concurrency)---- This module is an internal module. The public API is provided in-- "Control.Concurrent.Async". Breaking changes to this module will not be-- reflected in a major bump, and using this module may break your code-- unless you are extremely careful.-------------------------------------------------------------------------------moduleControl.Concurrent.Async.InternalwhereimportControl.Concurrent.STMimportControl.ExceptionimportControl.ConcurrentimportqualifiedData.FoldableasF #if !MIN_VERSION_base(4,6,0) importPreludehiding(catch) #endif importControl.MonadimportControl.Applicative #if !MIN_VERSION_base(4,8,0) importData.Monoid(Monoid(mempty,mappend))importData.Traversable #endif #if __GLASGOW_HASKELL__ < 710 importData.Typeable #endif #if MIN_VERSION_base(4,8,0) importData.Bifunctor #endif #if MIN_VERSION_base(4,9,0) importData.Semigroup(Semigroup((<>))) #endif importData.Hashable(Hashable(hashWithSalt))importData.IORefimportGHC.ExtsimportGHC.IOhiding(finally,onException)importGHC.Conc-- ------------------------------------------------------------------------------- STM Async API-- | An asynchronous action spawned by 'async' or 'withAsync'.-- Asynchronous actions are executed in a separate thread, and-- operations are provided for waiting for asynchronous actions to-- complete and obtaining their results (see e.g. 'wait').--dataAsync a =Async {forall a. Async a -> ThreadId asyncThreadId ::{-# UNPACK#-}!ThreadId-- ^ Returns the 'ThreadId' of the thread running-- the given 'Async'.,forall a. Async a -> STM (Either SomeException a) _asyncWait ::STM(EitherSomeExceptiona )}instanceEq(Async a )whereAsync ThreadId a STM (Either SomeException a) _== :: Async a -> Async a -> Bool ==Async ThreadId b STM (Either SomeException a) _=ThreadId a forall a. Eq a => a -> a -> Bool ==ThreadId b instanceOrd(Async a )whereAsync ThreadId a STM (Either SomeException a) _compare :: Async a -> Async a -> Ordering `compare`Async ThreadId b STM (Either SomeException a) _=ThreadId a forall a. Ord a => a -> a -> Ordering `compare`ThreadId b instanceHashable(Async a )wherehashWithSalt :: Int -> Async a -> Int hashWithSalt Int salt (Async ThreadId a STM (Either SomeException a) _)=forall a. Hashable a => Int -> a -> Int hashWithSaltInt salt ThreadId a instanceFunctorAsync wherefmap :: forall a b. (a -> b) -> Async a -> Async b fmapa -> b f (Async ThreadId a STM (Either SomeException a) w )=forall a. ThreadId -> STM (Either SomeException a) -> Async a Async ThreadId a (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> b f )STM (Either SomeException a) w )-- | Compare two Asyncs that may have different types by their 'ThreadId'.compareAsyncs ::Async a ->Async b ->OrderingcompareAsyncs :: forall a b. Async a -> Async b -> Ordering compareAsyncs (Async ThreadId t1 STM (Either SomeException a) _)(Async ThreadId t2 STM (Either SomeException b) _)=forall a. Ord a => a -> a -> Ordering compareThreadId t1 ThreadId t2 -- | Spawn an asynchronous action in a separate thread.---- Like for 'forkIO', the action may be left running unintentionally-- (see module-level documentation for details).---- __Use 'withAsync' style functions wherever you can instead!__async ::IOa ->IO(Async a )async :: forall a. IO a -> IO (Async a) async =forall a. a -> a inlineforall a. (IO () -> IO ThreadId) -> IO a -> IO (Async a) asyncUsing IO () -> IO ThreadId rawForkIO -- | Like 'async' but using 'forkOS' internally.asyncBound ::IOa ->IO(Async a )asyncBound :: forall a. IO a -> IO (Async a) asyncBound =forall a. (IO () -> IO ThreadId) -> IO a -> IO (Async a) asyncUsing IO () -> IO ThreadId forkOS-- | Like 'async' but using 'forkOn' internally.asyncOn ::Int->IOa ->IO(Async a )asyncOn :: forall a. Int -> IO a -> IO (Async a) asyncOn =forall a. (IO () -> IO ThreadId) -> IO a -> IO (Async a) asyncUsing forall b c a. (b -> c) -> (a -> b) -> a -> c .Int -> IO () -> IO ThreadId rawForkOn -- | Like 'async' but using 'forkIOWithUnmask' internally. The child-- thread is passed a function that can be used to unmask asynchronous-- exceptions.asyncWithUnmask ::((forallb .IOb ->IOb )->IOa )->IO(Async a )asyncWithUnmask :: forall a. ((forall b. IO b -> IO b) -> IO a) -> IO (Async a) asyncWithUnmask (forall b. IO b -> IO b) -> IO a actionWith =forall a. (IO () -> IO ThreadId) -> IO a -> IO (Async a) asyncUsing IO () -> IO ThreadId rawForkIO ((forall b. IO b -> IO b) -> IO a actionWith forall b. IO b -> IO b unsafeUnmask)-- | Like 'asyncOn' but using 'forkOnWithUnmask' internally. The-- child thread is passed a function that can be used to unmask-- asynchronous exceptions.asyncOnWithUnmask ::Int->((forallb .IOb ->IOb )->IOa )->IO(Async a )asyncOnWithUnmask :: forall a. Int -> ((forall b. IO b -> IO b) -> IO a) -> IO (Async a) asyncOnWithUnmask Int cpu (forall b. IO b -> IO b) -> IO a actionWith =forall a. (IO () -> IO ThreadId) -> IO a -> IO (Async a) asyncUsing (Int -> IO () -> IO ThreadId rawForkOn Int cpu )((forall b. IO b -> IO b) -> IO a actionWith forall b. IO b -> IO b unsafeUnmask)asyncUsing ::(IO()->IOThreadId)->IOa ->IO(Async a )asyncUsing :: forall a. (IO () -> IO ThreadId) -> IO a -> IO (Async a) asyncUsing IO () -> IO ThreadId doFork =\IO a action ->doTMVar (Either SomeException a) var <-forall a. IO (TMVar a) newEmptyTMVarIO-- t <- forkFinally action (\r -> atomically $ putTMVar var r)-- slightly faster:ThreadId t <-forall b. ((forall b. IO b -> IO b) -> IO b) -> IO b maskforall a b. (a -> b) -> a -> b $\forall b. IO b -> IO b restore ->IO () -> IO ThreadId doFork forall a b. (a -> b) -> a -> b $forall e a. Exception e => IO a -> IO (Either e a) try(forall b. IO b -> IO b restore IO a action )forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>=forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. TMVar a -> a -> STM () putTMVarTMVar (Either SomeException a) var forall (m :: * -> *) a. Monad m => a -> m a return(forall a. ThreadId -> STM (Either SomeException a) -> Async a Async ThreadId t (forall a. TMVar a -> STM a readTMVarTMVar (Either SomeException a) var ))-- | 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, 'uninterruptibleCancel' is called on the @Async@.---- > withAsync action inner = mask $ \restore -> do-- > a <- async (restore action)-- > restore (inner a) `finally` uninterruptibleCancel a---- This is a useful variant of 'async' that ensures an @Async@ is-- never left running unintentionally.---- Note: a reference to the child thread is kept alive until the call-- to `withAsync` returns, so nesting many `withAsync` calls requires-- linear memory.--withAsync ::IOa ->(Async a ->IOb )->IOb withAsync :: forall a b. IO a -> (Async a -> IO b) -> IO b withAsync =forall a. a -> a inlineforall a b. (IO () -> IO ThreadId) -> IO a -> (Async a -> IO b) -> IO b withAsyncUsing IO () -> IO ThreadId rawForkIO -- | Like 'withAsync' but uses 'forkOS' internally.withAsyncBound ::IOa ->(Async a ->IOb )->IOb withAsyncBound :: forall a b. IO a -> (Async a -> IO b) -> IO b withAsyncBound =forall a b. (IO () -> IO ThreadId) -> IO a -> (Async a -> IO b) -> IO b withAsyncUsing IO () -> IO ThreadId forkOS-- | Like 'withAsync' but uses 'forkOn' internally.withAsyncOn ::Int->IOa ->(Async a ->IOb )->IOb withAsyncOn :: forall a b. Int -> IO a -> (Async a -> IO b) -> IO b withAsyncOn =forall a b. (IO () -> IO ThreadId) -> IO a -> (Async a -> IO b) -> IO b withAsyncUsing forall b c a. (b -> c) -> (a -> b) -> a -> c .Int -> IO () -> IO ThreadId rawForkOn -- | Like 'withAsync' but uses 'forkIOWithUnmask' internally. The-- child thread is passed a function that can be used to unmask-- asynchronous exceptions.withAsyncWithUnmask ::((forallc .IOc ->IOc )->IOa )->(Async a ->IOb )->IOb withAsyncWithUnmask :: forall a b. ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b withAsyncWithUnmask (forall b. IO b -> IO b) -> IO a actionWith =forall a b. (IO () -> IO ThreadId) -> IO a -> (Async a -> IO b) -> IO b withAsyncUsing IO () -> IO ThreadId rawForkIO ((forall b. IO b -> IO b) -> IO a actionWith forall b. IO b -> IO b unsafeUnmask)-- | Like 'withAsyncOn' but uses 'forkOnWithUnmask' internally. The-- child thread is passed a function that can be used to unmask-- asynchronous exceptionswithAsyncOnWithUnmask ::Int->((forallc .IOc ->IOc )->IOa )->(Async a ->IOb )->IOb withAsyncOnWithUnmask :: forall a b. Int -> ((forall b. IO b -> IO b) -> IO a) -> (Async a -> IO b) -> IO b withAsyncOnWithUnmask Int cpu (forall b. IO b -> IO b) -> IO a actionWith =forall a b. (IO () -> IO ThreadId) -> IO a -> (Async a -> IO b) -> IO b withAsyncUsing (Int -> IO () -> IO ThreadId rawForkOn Int cpu )((forall b. IO b -> IO b) -> IO a actionWith forall b. IO b -> IO b unsafeUnmask)withAsyncUsing ::(IO()->IOThreadId)->IOa ->(Async a ->IOb )->IOb -- The bracket version works, but is slow. We can do better by-- hand-coding it:withAsyncUsing :: forall a b. (IO () -> IO ThreadId) -> IO a -> (Async a -> IO b) -> IO b withAsyncUsing IO () -> IO ThreadId doFork =\IO a action Async a -> IO b inner ->doTMVar (Either SomeException a) var <-forall a. IO (TMVar a) newEmptyTMVarIOforall b. ((forall b. IO b -> IO b) -> IO b) -> IO b maskforall a b. (a -> b) -> a -> b $\forall b. IO b -> IO b restore ->doThreadId t <-IO () -> IO ThreadId doFork forall a b. (a -> b) -> a -> b $forall e a. Exception e => IO a -> IO (Either e a) try(forall b. IO b -> IO b restore IO a action )forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>=forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. TMVar a -> a -> STM () putTMVarTMVar (Either SomeException a) var leta :: Async a a =forall a. ThreadId -> STM (Either SomeException a) -> Async a Async ThreadId t (forall a. TMVar a -> STM a readTMVarTMVar (Either SomeException a) var )b r <-forall b. IO b -> IO b restore (Async a -> IO b inner Async a a )forall a. IO a -> (SomeException -> IO a) -> IO a `catchAll` \SomeException e ->doforall a. Async a -> IO () uninterruptibleCancel Async a a forall e a. Exception e => e -> IO a throwIOSomeException e forall a. Async a -> IO () uninterruptibleCancel Async a a forall (m :: * -> *) a. Monad m => a -> m a returnb r -- | Wait for an asynchronous action to complete, and return its-- value. If the asynchronous action threw an exception, then the-- exception is re-thrown by 'wait'.---- > wait = atomically . waitSTM--{-# INLINEwait #-}wait ::Async a ->IOa wait :: forall a. Async a -> IO a wait =forall b. IO b -> IO b tryAgain forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Async a -> STM a waitSTM where-- See: https://github.com/simonmar/async/issues/14tryAgain :: IO a -> IO a tryAgain IO a f =IO a f forall e a. Exception e => IO a -> (e -> IO a) -> IO a `catch`\BlockedIndefinitelyOnSTM BlockedIndefinitelyOnSTM->IO a f -- | 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@.---- > waitCatch = atomically . waitCatchSTM--{-# INLINEwaitCatch #-}waitCatch ::Async a ->IO(EitherSomeExceptiona )waitCatch :: forall a. Async a -> IO (Either SomeException a) waitCatch =forall b. IO b -> IO b tryAgain forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Async a -> STM (Either SomeException a) waitCatchSTM where-- See: https://github.com/simonmar/async/issues/14tryAgain :: IO a -> IO a tryAgain IO a f =IO a f forall e a. Exception e => IO a -> (e -> IO a) -> IO a `catch`\BlockedIndefinitelyOnSTM BlockedIndefinitelyOnSTM->IO a f -- | Check whether an 'Async' has completed yet. If it has not-- completed yet, then the result is @Nothing@, otherwise the result-- is @Just e@ where @e@ is @Left x@ if the @Async@ raised an-- exception @x@, or @Right a@ if it returned a value @a@.---- > poll = atomically . pollSTM--{-# INLINEpoll #-}poll ::Async a ->IO(Maybe(EitherSomeExceptiona ))poll :: forall a. Async a -> IO (Maybe (Either SomeException a)) poll =forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Async a -> STM (Maybe (Either SomeException a)) pollSTM -- | A version of 'wait' that can be used inside an STM transaction.--waitSTM ::Async a ->STMa waitSTM :: forall a. Async a -> STM a waitSTM Async a a =doEither SomeException a r <-forall a. Async a -> STM (Either SomeException a) waitCatchSTM Async a a forall a c b. (a -> c) -> (b -> c) -> Either a b -> c eitherforall e a. Exception e => e -> STM a throwSTMforall (m :: * -> *) a. Monad m => a -> m a returnEither SomeException a r -- | A version of 'waitCatch' that can be used inside an STM transaction.--{-# INLINEwaitCatchSTM #-}waitCatchSTM ::Async a ->STM(EitherSomeExceptiona )waitCatchSTM :: forall a. Async a -> STM (Either SomeException a) waitCatchSTM (Async ThreadId _STM (Either SomeException a) w )=STM (Either SomeException a) w -- | A version of 'poll' that can be used inside an STM transaction.--{-# INLINEpollSTM #-}pollSTM ::Async a ->STM(Maybe(EitherSomeExceptiona ))pollSTM :: forall a. Async a -> STM (Maybe (Either SomeException a)) pollSTM (Async ThreadId _STM (Either SomeException a) w )=(forall a. a -> Maybe a Justforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>STM (Either SomeException a) w )forall a. STM a -> STM a -> STM a `orElse`forall (m :: * -> *) a. Monad m => a -> m a returnforall a. Maybe a Nothing-- | Cancel an asynchronous action by throwing the @AsyncCancelled@-- 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) AsyncCancelled <* waitCatch a---- Note that 'cancel' will not terminate until the thread the 'Async'-- refers to has terminated. This means that 'cancel' will block for-- as long said thread blocks when receiving an asynchronous exception.---- For example, it could block if:---- * It's executing a foreign call, and thus cannot receive the asynchronous-- exception;-- * It's executing some cleanup handler after having received the exception,-- and the handler is blocking.{-# INLINEcancel #-}cancel ::Async a ->IO()cancel :: forall a. Async a -> IO () cancel a :: Async a a @(Async ThreadId t STM (Either SomeException a) _)=forall e. Exception e => ThreadId -> e -> IO () throwToThreadId t AsyncCancelled AsyncCancelled forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a <*forall a. Async a -> IO (Either SomeException a) waitCatch Async a a -- | Cancel multiple asynchronous actions by throwing the @AsyncCancelled@-- exception to each of them in turn, then waiting for all the `Async` threads-- to complete.cancelMany ::[Async a ]->IO()cancelMany :: forall a. [Async a] -> IO () cancelMany [Async a] as =doforall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => (a -> m b) -> t a -> m () mapM_(\(Async ThreadId t STM (Either SomeException a) _)->forall e. Exception e => ThreadId -> e -> IO () throwToThreadId t AsyncCancelled AsyncCancelled )[Async a] as forall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => (a -> m b) -> t a -> m () mapM_forall a. Async a -> IO (Either SomeException a) waitCatch [Async a] as -- | The exception thrown by `cancel` to terminate a thread.dataAsyncCancelled =AsyncCancelled deriving(Int -> AsyncCancelled -> ShowS [AsyncCancelled] -> ShowS AsyncCancelled -> String forall a. (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a showList :: [AsyncCancelled] -> ShowS $cshowList :: [AsyncCancelled] -> ShowS show :: AsyncCancelled -> String $cshow :: AsyncCancelled -> String showsPrec :: Int -> AsyncCancelled -> ShowS $cshowsPrec :: Int -> AsyncCancelled -> ShowS Show,AsyncCancelled -> AsyncCancelled -> Bool forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: AsyncCancelled -> AsyncCancelled -> Bool $c/= :: AsyncCancelled -> AsyncCancelled -> Bool == :: AsyncCancelled -> AsyncCancelled -> Bool $c== :: AsyncCancelled -> AsyncCancelled -> Bool Eq #if __GLASGOW_HASKELL__ < 710 ,Typeable #endif )instanceExceptionAsyncCancelled where #if __GLASGOW_HASKELL__ >= 708 fromException :: SomeException -> Maybe AsyncCancelled fromException=forall e. Exception e => SomeException -> Maybe e asyncExceptionFromExceptiontoException :: AsyncCancelled -> SomeException toException=forall e. Exception e => e -> SomeException asyncExceptionToException #endif -- | Cancel an asynchronous action---- This is a variant of `cancel`, but it is not interruptible.{-# INLINEuninterruptibleCancel #-}uninterruptibleCancel ::Async a ->IO()uninterruptibleCancel :: forall a. Async a -> IO () uninterruptibleCancel =forall b. IO b -> IO b uninterruptibleMask_forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Async a -> IO () cancel -- | Cancel an asynchronous action by throwing the supplied exception-- to it.---- > cancelWith a x = throwTo (asyncThreadId a) x---- The notes about the synchronous nature of 'cancel' also apply to-- 'cancelWith'.cancelWith ::Exceptione =>Async a ->e ->IO()cancelWith :: forall e a. Exception e => Async a -> e -> IO () cancelWith a :: Async a a @(Async ThreadId t STM (Either SomeException a) _)e e =forall e. Exception e => ThreadId -> e -> IO () throwToThreadId t e e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a <*forall a. Async a -> IO (Either SomeException a) waitCatch Async a a -- | Wait for any of the supplied asynchronous operations to complete.-- The value returned is a pair of the 'Async' that completed, and the-- result that would be returned by 'wait' on that 'Async'.-- The input list must be non-empty.---- If multiple 'Async's complete or have completed, then the value-- returned corresponds to the first completed 'Async' in the list.--{-# INLINEwaitAnyCatch #-}waitAnyCatch ::[Async a ]->IO(Async a ,EitherSomeExceptiona )waitAnyCatch :: forall a. [Async a] -> IO (Async a, Either SomeException a) waitAnyCatch =forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. [Async a] -> STM (Async a, Either SomeException a) waitAnyCatchSTM -- | A version of 'waitAnyCatch' that can be used inside an STM transaction.---- @since 2.1.0waitAnyCatchSTM ::[Async a ]->STM(Async a ,EitherSomeExceptiona )waitAnyCatchSTM :: forall a. [Async a] -> STM (Async a, Either SomeException a) waitAnyCatchSTM []=forall e a. Exception e => e -> STM a throwSTMforall a b. (a -> b) -> a -> b $String -> ErrorCall ErrorCallString "waitAnyCatchSTM: invalid argument: input list must be non-empty"waitAnyCatchSTM [Async a] asyncs =forall (t :: * -> *) a b. Foldable t => (a -> b -> b) -> b -> t a -> b foldrforall a. STM a -> STM a -> STM a orElseforall a. STM a retryforall a b. (a -> b) -> a -> b $forall a b. (a -> b) -> [a] -> [b] map(\Async a a ->doEither SomeException a r <-forall a. Async a -> STM (Either SomeException a) waitCatchSTM Async a a ;forall (m :: * -> *) a. Monad m => a -> m a return(Async a a ,Either SomeException a r ))[Async a] asyncs -- | Like 'waitAnyCatch', but also cancels the other asynchronous-- operations as soon as one has completed.--waitAnyCatchCancel ::[Async a ]->IO(Async a ,EitherSomeExceptiona )waitAnyCatchCancel :: forall a. [Async a] -> IO (Async a, Either SomeException a) waitAnyCatchCancel [Async a] asyncs =forall a. [Async a] -> IO (Async a, Either SomeException a) waitAnyCatch [Async a] asyncs forall a b. IO a -> IO b -> IO a `finally`forall a. [Async a] -> IO () cancelMany [Async a] asyncs -- | Wait for any of the supplied @Async@s to complete. If the first-- to complete throws an exception, then that exception is re-thrown-- by 'waitAny'.-- The input list must be non-empty.---- If multiple 'Async's complete or have completed, then the value-- returned corresponds to the first completed 'Async' in the list.--{-# INLINEwaitAny #-}waitAny ::[Async a ]->IO(Async a ,a )waitAny :: forall a. [Async a] -> IO (Async a, a) waitAny =forall a. STM a -> IO a atomicallyforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. [Async a] -> STM (Async a, a) waitAnySTM -- | A version of 'waitAny' that can be used inside an STM transaction.---- @since 2.1.0waitAnySTM ::[Async a ]->STM(Async a ,a )waitAnySTM :: forall a. [Async a] -> STM (Async a, a) waitAnySTM []=forall e a. Exception e => e -> STM a throwSTMforall a b. (a -> b) -> a -> b $String -> ErrorCall ErrorCallString "waitAnySTM: invalid argument: input list must be non-empty"waitAnySTM [Async a] asyncs =forall (t :: * -> *) a b. Foldable t => (a -> b -> b) -> b -> t a -> b foldrforall a. STM a -> STM a -> STM a orElseforall a. STM a retryforall a b. (a -> b) -> a -> b $forall a b. (a -> b) -> [a] -> [b] map(\Async a a ->doa r <-forall a. Async a -> STM a waitSTM Async a a ;forall (m :: * -> *) a. Monad m => a -> m a return(Async a a ,a r ))[Async a] asyncs -- | Like 'waitAny', but also cancels the other asynchronous-- operations as soon as one has completed.--waitAnyCancel ::[Async a ]->IO(Async a ,a )waitAnyCancel :: forall a. [Async a] -> IO (Async a, a) waitAnyCancel [Async a] asyncs =forall a. [Async a] -> IO (Async a, a) waitAny [Async a] asyncs forall a b. IO a -> IO b -> IO a `finally`forall a. [Async a] -> IO () cancelMany [Async a] asyncs -- | Wait for the first of two @Async@s to finish.{-# INLINEwaitEitherCatch #-}waitEitherCatch ::Async a ->Async b ->IO(Either(EitherSomeExceptiona )(EitherSomeExceptionb ))waitEitherCatch :: forall a b. Async a -> Async b -> IO (Either (Either SomeException a) (Either SomeException b)) waitEitherCatch Async a left Async b right =forall b. IO b -> IO b tryAgain forall a b. (a -> b) -> a -> b $forall a. STM a -> IO a atomically(forall a b. Async a -> Async b -> STM (Either (Either SomeException a) (Either SomeException b)) waitEitherCatchSTM Async a left Async b right )where-- See: https://github.com/simonmar/async/issues/14tryAgain :: IO a -> IO a tryAgain IO a f =IO a f forall e a. Exception e => IO a -> (e -> IO a) -> IO a `catch`\BlockedIndefinitelyOnSTM BlockedIndefinitelyOnSTM->IO a f -- | A version of 'waitEitherCatch' that can be used inside an STM transaction.---- @since 2.1.0waitEitherCatchSTM ::Async a ->Async b ->STM(Either(EitherSomeExceptiona )(EitherSomeExceptionb ))waitEitherCatchSTM :: forall a b. Async a -> Async b -> STM (Either (Either SomeException a) (Either SomeException b)) waitEitherCatchSTM Async a left Async b right =(forall a b. a -> Either a b Leftforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall a. Async a -> STM (Either SomeException a) waitCatchSTM Async a left )forall a. STM a -> STM a -> STM a `orElse`(forall a b. b -> Either a b Rightforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall a. Async a -> STM (Either SomeException a) waitCatchSTM Async b right )-- | Like 'waitEitherCatch', but also 'cancel's both @Async@s before-- returning.--waitEitherCatchCancel ::Async a ->Async b ->IO(Either(EitherSomeExceptiona )(EitherSomeExceptionb ))waitEitherCatchCancel :: forall a b. Async a -> Async b -> IO (Either (Either SomeException a) (Either SomeException b)) waitEitherCatchCancel Async a left Async b right =forall a b. Async a -> Async b -> IO (Either (Either SomeException a) (Either SomeException b)) waitEitherCatch Async a left Async b right forall a b. IO a -> IO b -> IO a `finally`forall a. [Async a] -> IO () cancelMany [()forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$Async a left ,()forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$Async b right ]-- | 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'.--{-# INLINEwaitEither #-}waitEither ::Async a ->Async b ->IO(Eithera b )waitEither :: forall a b. Async a -> Async b -> IO (Either a b) waitEither Async a left Async b right =forall a. STM a -> IO a atomically(forall a b. Async a -> Async b -> STM (Either a b) waitEitherSTM Async a left Async b right )-- | A version of 'waitEither' that can be used inside an STM transaction.---- @since 2.1.0waitEitherSTM ::Async a ->Async b ->STM(Eithera b )waitEitherSTM :: forall a b. Async a -> Async b -> STM (Either a b) waitEitherSTM Async a left Async b right =(forall a b. a -> Either a b Leftforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall a. Async a -> STM a waitSTM Async a left )forall a. STM a -> STM a -> STM a `orElse`(forall a b. b -> Either a b Rightforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall a. Async a -> STM a waitSTM Async b right )-- | Like 'waitEither', but the result is ignored.--{-# INLINEwaitEither_ #-}waitEither_ ::Async a ->Async b ->IO()waitEither_ :: forall a b. Async a -> Async b -> IO () waitEither_ Async a left Async b right =forall a. STM a -> IO a atomically(forall a b. Async a -> Async b -> STM () waitEitherSTM_ Async a left Async b right )-- | A version of 'waitEither_' that can be used inside an STM transaction.---- @since 2.1.0waitEitherSTM_ ::Async a ->Async b ->STM()waitEitherSTM_ :: forall a b. Async a -> Async b -> STM () waitEitherSTM_ Async a left Async b right =(forall (f :: * -> *) a. Functor f => f a -> f () voidforall a b. (a -> b) -> a -> b $forall a. Async a -> STM a waitSTM Async a left )forall a. STM a -> STM a -> STM a `orElse`(forall (f :: * -> *) a. Functor f => f a -> f () voidforall a b. (a -> b) -> a -> b $forall a. Async a -> STM a waitSTM Async b right )-- | Like 'waitEither', but also 'cancel's both @Async@s before-- returning.--waitEitherCancel ::Async a ->Async b ->IO(Eithera b )waitEitherCancel :: forall a b. Async a -> Async b -> IO (Either a b) waitEitherCancel Async a left Async b right =forall a b. Async a -> Async b -> IO (Either a b) waitEither Async a left Async b right forall a b. IO a -> IO b -> IO a `finally`forall a. [Async a] -> IO () cancelMany [()forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$Async a left ,()forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$Async b 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'.--{-# INLINEwaitBoth #-}waitBoth ::Async a ->Async b ->IO(a ,b )waitBoth :: forall a b. Async a -> Async b -> IO (a, b) waitBoth Async a left Async b right =forall b. IO b -> IO b tryAgain forall a b. (a -> b) -> a -> b $forall a. STM a -> IO a atomically(forall a b. Async a -> Async b -> STM (a, b) waitBothSTM Async a left Async b right )where-- See: https://github.com/simonmar/async/issues/14tryAgain :: IO a -> IO a tryAgain IO a f =IO a f forall e a. Exception e => IO a -> (e -> IO a) -> IO a `catch`\BlockedIndefinitelyOnSTM BlockedIndefinitelyOnSTM->IO a f -- | A version of 'waitBoth' that can be used inside an STM transaction.---- @since 2.1.0waitBothSTM ::Async a ->Async b ->STM(a ,b )waitBothSTM :: forall a b. Async a -> Async b -> STM (a, b) waitBothSTM Async a left Async b right =doa a <-forall a. Async a -> STM a waitSTM Async a left forall a. STM a -> STM a -> STM a `orElse`(forall a. Async a -> STM a waitSTM Async b right forall (m :: * -> *) a b. Monad m => m a -> m b -> m b >>forall a. STM a retry)b b <-forall a. Async a -> STM a waitSTM Async b right forall (m :: * -> *) a. Monad m => a -> m a return(a a ,b b )-- ------------------------------------------------------------------------------- Linking threadsdataExceptionInLinkedThread =foralla .ExceptionInLinkedThread (Async a )SomeException #if __GLASGOW_HASKELL__ < 710 derivingTypeable #endif instanceShowExceptionInLinkedThread whereshowsPrec :: Int -> ExceptionInLinkedThread -> ShowS showsPrecInt p (ExceptionInLinkedThread (Async ThreadId t STM (Either SomeException a) _)SomeException e )=Bool -> ShowS -> ShowS showParen(Int p forall a. Ord a => a -> a -> Bool >=Int 11)forall a b. (a -> b) -> a -> b $String -> ShowS showStringString "ExceptionInLinkedThread "forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Show a => Int -> a -> ShowS showsPrecInt 11ThreadId t forall b c a. (b -> c) -> (a -> b) -> a -> c .String -> ShowS showStringString " "forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Show a => Int -> a -> ShowS showsPrecInt 11SomeException e instanceExceptionExceptionInLinkedThread where #if __GLASGOW_HASKELL__ >= 708 fromException :: SomeException -> Maybe ExceptionInLinkedThread fromException =forall e. Exception e => SomeException -> Maybe e asyncExceptionFromExceptiontoException :: ExceptionInLinkedThread -> SomeException toException =forall e. Exception e => e -> SomeException asyncExceptionToException #endif -- | Link the given @Async@ to the current thread, such that if the-- @Async@ raises an exception, that exception will be re-thrown in-- the current thread, wrapped in 'ExceptionInLinkedThread'.---- 'link' ignores 'AsyncCancelled' exceptions thrown in the other thread,-- so that it's safe to 'cancel' a thread you're linked to. If you want-- different behaviour, use 'linkOnly'.--link ::Async a ->IO()link :: forall a. Async a -> IO () link =forall a. (SomeException -> Bool) -> Async a -> IO () linkOnly (Bool -> Bool notforall b c a. (b -> c) -> (a -> b) -> a -> c .SomeException -> Bool isCancel )-- | Link the given @Async@ to the current thread, such that if the-- @Async@ raises an exception, that exception will be re-thrown in-- the current thread, wrapped in 'ExceptionInLinkedThread'.---- The supplied predicate determines which exceptions in the target-- thread should be propagated to the source thread.--linkOnly ::(SomeException->Bool)-- ^ return 'True' if the exception-- should be propagated, 'False'-- otherwise.->Async a ->IO()linkOnly :: forall a. (SomeException -> Bool) -> Async a -> IO () linkOnly SomeException -> Bool shouldThrow Async a a =doThreadId me <-IO ThreadId myThreadIdforall (f :: * -> *) a. Functor f => f a -> f () voidforall a b. (a -> b) -> a -> b $forall a. IO a -> IO ThreadId forkRepeat forall a b. (a -> b) -> a -> b $doEither SomeException a r <-forall a. Async a -> IO (Either SomeException a) waitCatch Async a a caseEither SomeException a r ofLeftSomeException e |SomeException -> Bool shouldThrow SomeException e ->forall e. Exception e => ThreadId -> e -> IO () throwToThreadId me (forall a. Async a -> SomeException -> ExceptionInLinkedThread ExceptionInLinkedThread Async a a SomeException e )Either SomeException a _otherwise ->forall (m :: * -> *) a. Monad m => a -> m a return()-- | Link two @Async@s together, such that if either raises an-- exception, the same exception is re-thrown in the other @Async@,-- wrapped in 'ExceptionInLinkedThread'.---- 'link2' ignores 'AsyncCancelled' exceptions, so that it's possible-- to 'cancel' either thread without cancelling the other. If you-- want different behaviour, use 'link2Only'.--link2 ::Async a ->Async b ->IO()link2 :: forall a b. Async a -> Async b -> IO () link2 =forall a b. (SomeException -> Bool) -> Async a -> Async b -> IO () link2Only (Bool -> Bool notforall b c a. (b -> c) -> (a -> b) -> a -> c .SomeException -> Bool isCancel )-- | Link two @Async@s together, such that if either raises an-- exception, the same exception is re-thrown in the other @Async@,-- wrapped in 'ExceptionInLinkedThread'.---- The supplied predicate determines which exceptions in the target-- thread should be propagated to the source thread.--link2Only ::(SomeException->Bool)->Async a ->Async b ->IO()link2Only :: forall a b. (SomeException -> Bool) -> Async a -> Async b -> IO () link2Only SomeException -> Bool shouldThrow left :: Async a left @(Async ThreadId tl STM (Either SomeException a) _)right :: Async b right @(Async ThreadId tr STM (Either SomeException b) _)=forall (f :: * -> *) a. Functor f => f a -> f () voidforall a b. (a -> b) -> a -> b $forall a. IO a -> IO ThreadId forkRepeat forall a b. (a -> b) -> a -> b $doEither (Either SomeException a) (Either SomeException b) r <-forall a b. Async a -> Async b -> IO (Either (Either SomeException a) (Either SomeException b)) waitEitherCatch Async a left Async b right caseEither (Either SomeException a) (Either SomeException b) r ofLeft(LeftSomeException e )|SomeException -> Bool shouldThrow SomeException e ->forall e. Exception e => ThreadId -> e -> IO () throwToThreadId tr (forall a. Async a -> SomeException -> ExceptionInLinkedThread ExceptionInLinkedThread Async a left SomeException e )Right(LeftSomeException e )|SomeException -> Bool shouldThrow SomeException e ->forall e. Exception e => ThreadId -> e -> IO () throwToThreadId tl (forall a. Async a -> SomeException -> ExceptionInLinkedThread ExceptionInLinkedThread Async b right SomeException e )Either (Either SomeException a) (Either SomeException b) _->forall (m :: * -> *) a. Monad m => a -> m a return()isCancel ::SomeException->BoolisCancel :: SomeException -> Bool isCancel SomeException e |JustAsyncCancelled AsyncCancelled <-forall e. Exception e => SomeException -> Maybe e fromExceptionSomeException e =Bool True|Bool otherwise=Bool False-- ------------------------------------------------------------------------------- | Run two @IO@ actions concurrently, and return the first to-- finish. The loser of the race is 'cancel'led.---- > race left right =-- > withAsync left $ \a ->-- > withAsync right $ \b ->-- > waitEither a b--race ::IOa ->IOb ->IO(Eithera b )-- | Like 'race', but the result is ignored.--race_ ::IOa ->IOb ->IO()-- | Run two @IO@ actions concurrently, and return both results. If-- either action throws an exception at any time, then the other-- action is 'cancel'led, and the exception is re-thrown by-- 'concurrently'.---- > concurrently left right =-- > withAsync left $ \a ->-- > withAsync right $ \b ->-- > waitBoth a bconcurrently ::IOa ->IOb ->IO(a ,b )-- | Run two @IO@ actions concurrently. If both of them end with @Right@,-- return both results. If one of then ends with @Left@, interrupt the other-- action and return the @Left@. --concurrentlyE ::IO(Eithere a )->IO(Eithere b )->IO(Eithere (a ,b ))-- | 'concurrently', but ignore the result values---- @since 2.1.1concurrently_ ::IOa ->IOb ->IO() #define USE_ASYNC_VERSIONS 0 #if USE_ASYNC_VERSIONS raceleftright=withAsyncleft$\a->withAsyncright$\b->waitEitherabrace_leftright=void$raceleftrightconcurrentlyleftright=withAsyncleft$\a->withAsyncright$\b->waitBothabconcurrently_leftright=void$concurrentlyleftright #else -- MVar versions of race/concurrently-- More ugly than the Async versions, but quite a bit faster.-- race :: IO a -> IO b -> IO (Either a b)race :: forall a b. IO a -> IO b -> IO (Either a b) race IO a left IO b right =forall a b r. IO a -> IO b -> (IO (Either SomeException (Either a b)) -> IO r) -> IO r concurrently' IO a left IO b right forall {e} {b}. Exception e => IO (Either e b) -> IO b collect wherecollect :: IO (Either e b) -> IO b collect IO (Either e b) m =doEither e b e <-IO (Either e b) m caseEither e b e ofLefte ex ->forall e a. Exception e => e -> IO a throwIOe ex Rightb r ->forall (m :: * -> *) a. Monad m => a -> m a returnb r -- race_ :: IO a -> IO b -> IO ()race_ :: forall a b. IO a -> IO b -> IO () race_ IO a left IO b right =forall (f :: * -> *) a. Functor f => f a -> f () voidforall a b. (a -> b) -> a -> b $forall a b. IO a -> IO b -> IO (Either a b) race IO a left IO b right -- concurrently :: IO a -> IO b -> IO (a,b)concurrently :: forall a b. IO a -> IO b -> IO (a, b) concurrently IO a left IO b right =forall a b r. IO a -> IO b -> (IO (Either SomeException (Either a b)) -> IO r) -> IO r concurrently' IO a left IO b right (forall {e} {a} {b}. Exception e => [Either a b] -> IO (Either e (Either a b)) -> IO (a, b) collect [])wherecollect :: [Either a b] -> IO (Either e (Either a b)) -> IO (a, b) collect [Lefta a ,Rightb b ]IO (Either e (Either a b)) _=forall (m :: * -> *) a. Monad m => a -> m a return(a a ,b b )collect [Rightb b ,Lefta a ]IO (Either e (Either a b)) _=forall (m :: * -> *) a. Monad m => a -> m a return(a a ,b b )collect [Either a b] xs IO (Either e (Either a b)) m =doEither e (Either a b) e <-IO (Either e (Either a b)) m caseEither e (Either a b) e ofLefte ex ->forall e a. Exception e => e -> IO a throwIOe ex RightEither a b r ->[Either a b] -> IO (Either e (Either a b)) -> IO (a, b) collect (Either a b r forall a. a -> [a] -> [a] :[Either a b] xs )IO (Either e (Either a b)) m -- concurrentlyE :: IO (Either e a) -> IO (Either e b) -> IO (Either e (a, b))concurrentlyE :: forall e a b. IO (Either e a) -> IO (Either e b) -> IO (Either e (a, b)) concurrentlyE IO (Either e a) left IO (Either e b) right =forall a b r. IO a -> IO b -> (IO (Either SomeException (Either a b)) -> IO r) -> IO r concurrently' IO (Either e a) left IO (Either e b) right (forall {e} {a} {a} {b}. Exception e => [Either (Either a a) (Either a b)] -> IO (Either e (Either (Either a a) (Either a b))) -> IO (Either a (a, b)) collect [])wherecollect :: [Either (Either a a) (Either a b)] -> IO (Either e (Either (Either a a) (Either a b))) -> IO (Either a (a, b)) collect [Left(Righta a ),Right(Rightb b )]IO (Either e (Either (Either a a) (Either a b))) _=forall (m :: * -> *) a. Monad m => a -> m a returnforall a b. (a -> b) -> a -> b $forall a b. b -> Either a b Right(a a ,b b )collect [Right(Rightb b ),Left(Righta a )]IO (Either e (Either (Either a a) (Either a b))) _=forall (m :: * -> *) a. Monad m => a -> m a returnforall a b. (a -> b) -> a -> b $forall a b. b -> Either a b Right(a a ,b b )collect (Left(Lefta ea ):[Either (Either a a) (Either a b)] _)IO (Either e (Either (Either a a) (Either a b))) _=forall (m :: * -> *) a. Monad m => a -> m a returnforall a b. (a -> b) -> a -> b $forall a b. a -> Either a b Lefta ea collect (Right(Lefta eb ):[Either (Either a a) (Either a b)] _)IO (Either e (Either (Either a a) (Either a b))) _=forall (m :: * -> *) a. Monad m => a -> m a returnforall a b. (a -> b) -> a -> b $forall a b. a -> Either a b Lefta eb collect [Either (Either a a) (Either a b)] xs IO (Either e (Either (Either a a) (Either a b))) m =doEither e (Either (Either a a) (Either a b)) e <-IO (Either e (Either (Either a a) (Either a b))) m caseEither e (Either (Either a a) (Either a b)) e ofLefte ex ->forall e a. Exception e => e -> IO a throwIOe ex RightEither (Either a a) (Either a b) r ->[Either (Either a a) (Either a b)] -> IO (Either e (Either (Either a a) (Either a b))) -> IO (Either a (a, b)) collect (Either (Either a a) (Either a b) r forall a. a -> [a] -> [a] :[Either (Either a a) (Either a b)] xs )IO (Either e (Either (Either a a) (Either a b))) m concurrently' ::IOa ->IOb ->(IO(EitherSomeException(Eithera b ))->IOr )->IOr concurrently' :: forall a b r. IO a -> IO b -> (IO (Either SomeException (Either a b)) -> IO r) -> IO r concurrently' IO a left IO b right IO (Either SomeException (Either a b)) -> IO r collect =doMVar (Either SomeException (Either a b)) done <-forall a. IO (MVar a) newEmptyMVarforall b. ((forall b. IO b -> IO b) -> IO b) -> IO b maskforall a b. (a -> b) -> a -> b $\forall b. IO b -> IO b restore ->do-- Note: uninterruptibleMask here is because we must not allow-- the putMVar in the exception handler to be interrupted,-- otherwise the parent thread will deadlock when it waits for-- the thread to terminate.ThreadId lid <-IO () -> IO ThreadId forkIOforall a b. (a -> b) -> a -> b $forall b. IO b -> IO b uninterruptibleMask_forall a b. (a -> b) -> a -> b $forall b. IO b -> IO b restore (IO a left forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>=forall a. MVar a -> a -> IO () putMVarMVar (Either SomeException (Either a b)) done forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a b. b -> Either a b Rightforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a b. a -> Either a b Left)forall a. IO a -> (SomeException -> IO a) -> IO a `catchAll` (forall a. MVar a -> a -> IO () putMVarMVar (Either SomeException (Either a b)) done forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a b. a -> Either a b Left)ThreadId rid <-IO () -> IO ThreadId forkIOforall a b. (a -> b) -> a -> b $forall b. IO b -> IO b uninterruptibleMask_forall a b. (a -> b) -> a -> b $forall b. IO b -> IO b restore (IO b right forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>=forall a. MVar a -> a -> IO () putMVarMVar (Either SomeException (Either a b)) done forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a b. b -> Either a b Rightforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a b. b -> Either a b Right)forall a. IO a -> (SomeException -> IO a) -> IO a `catchAll` (forall a. MVar a -> a -> IO () putMVarMVar (Either SomeException (Either a b)) done forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a b. a -> Either a b Left)IORef Int count <-forall a. a -> IO (IORef a) newIORef(Int 2::Int)lettakeDone :: IO (Either SomeException (Either a b)) takeDone =doEither SomeException (Either a b) r <-forall a. MVar a -> IO a takeMVarMVar (Either SomeException (Either a b)) done -- interruptible-- Decrement the counter so we know how many takes are left.-- Since only the parent thread is calling this, we can-- use non-atomic modifications.-- NB. do this *after* takeMVar, because takeMVar might be-- interrupted.forall a. IORef a -> (a -> a) -> IO () modifyIORefIORef Int count (forall a. Num a => a -> a -> a subtractInt 1)forall (m :: * -> *) a. Monad m => a -> m a returnEither SomeException (Either a b) r lettryAgain :: IO a -> IO a tryAgain IO a f =IO a f forall e a. Exception e => IO a -> (e -> IO a) -> IO a `catch`\BlockedIndefinitelyOnMVar BlockedIndefinitelyOnMVar->IO a f stop :: IO () stop =do-- kill right before left, to match the semantics of-- the version using withAsync. (#27)forall b. IO b -> IO b uninterruptibleMask_forall a b. (a -> b) -> a -> b $doInt count' <-forall a. IORef a -> IO a readIORefIORef Int count -- we only need to use killThread if there are still-- children alive. Note: forkIO here is because the-- child thread could be in an uninterruptible-- putMVar.forall (f :: * -> *). Applicative f => Bool -> f () -> f () when(Int count' forall a. Ord a => a -> a -> Bool >Int 0)forall a b. (a -> b) -> a -> b $forall (f :: * -> *) a. Functor f => f a -> f () voidforall a b. (a -> b) -> a -> b $IO () -> IO ThreadId forkIOforall a b. (a -> b) -> a -> b $doforall e. Exception e => ThreadId -> e -> IO () throwToThreadId rid AsyncCancelled AsyncCancelled forall e. Exception e => ThreadId -> e -> IO () throwToThreadId lid AsyncCancelled AsyncCancelled -- ensure the children are really deadforall (m :: * -> *) a. Applicative m => Int -> m a -> m () replicateM_Int count' (forall b. IO b -> IO b tryAgain forall a b. (a -> b) -> a -> b $forall a. MVar a -> IO a takeMVarMVar (Either SomeException (Either a b)) done )r r <-IO (Either SomeException (Either a b)) -> IO r collect (forall b. IO b -> IO b tryAgain forall a b. (a -> b) -> a -> b $IO (Either SomeException (Either a b)) takeDone )forall a b. IO a -> IO b -> IO a `onException`IO () stop IO () stop forall (m :: * -> *) a. Monad m => a -> m a returnr r concurrently_ :: forall a b. IO a -> IO b -> IO () concurrently_ IO a left IO b right =forall a b r. IO a -> IO b -> (IO (Either SomeException (Either a b)) -> IO r) -> IO r concurrently' IO a left IO b right (forall {e} {b}. Exception e => Int -> IO (Either e b) -> IO () collect Int 0)wherecollect :: Int -> IO (Either e b) -> IO () collect Int 2IO (Either e b) _=forall (m :: * -> *) a. Monad m => a -> m a return()collect Int i IO (Either e b) m =doEither e b e <-IO (Either e b) m caseEither e b e ofLefte ex ->forall e a. Exception e => e -> IO a throwIOe ex Rightb _->Int -> IO (Either e b) -> IO () collect (Int i forall a. Num a => a -> a -> a +Int 1::Int)IO (Either e b) m #endif -- | Maps an 'IO'-performing function over any 'Traversable' data-- type, performing all the @IO@ actions concurrently, and returning-- the original data structure with the arguments replaced by the-- results.---- If any of the actions throw an exception, then all other actions are-- cancelled and the exception is re-thrown.---- For example, @mapConcurrently@ works with lists:---- > pages <- mapConcurrently getURL ["url1", "url2", "url3"]---- Take into account that @async@ will try to immediately spawn a thread-- for each element of the @Traversable@, so running this on large-- inputs without care may lead to resource exhaustion (of memory,-- file descriptors, or other limited resources).mapConcurrently ::Traversablet =>(a ->IOb )->t a ->IO(t b )mapConcurrently :: forall (t :: * -> *) a b. Traversable t => (a -> IO b) -> t a -> IO (t b) mapConcurrently a -> IO b f =forall a. Concurrently a -> IO a runConcurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (t :: * -> *) (f :: * -> *) a b. (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b) traverse(forall a. IO a -> Concurrently a Concurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .a -> IO b f )-- | `forConcurrently` is `mapConcurrently` with its arguments flipped---- > pages <- forConcurrently ["url1", "url2", "url3"] $ \url -> getURL url---- @since 2.1.0forConcurrently ::Traversablet =>t a ->(a ->IOb )->IO(t b )forConcurrently :: forall (t :: * -> *) a b. Traversable t => t a -> (a -> IO b) -> IO (t b) forConcurrently =forall a b c. (a -> b -> c) -> b -> a -> c flipforall (t :: * -> *) a b. Traversable t => (a -> IO b) -> t a -> IO (t b) mapConcurrently -- | `mapConcurrently_` is `mapConcurrently` with the return value discarded;-- a concurrent equivalent of 'mapM_'.mapConcurrently_ ::F.Foldablef =>(a ->IOb )->f a ->IO()mapConcurrently_ :: forall (f :: * -> *) a b. Foldable f => (a -> IO b) -> f a -> IO () mapConcurrently_ a -> IO b f =forall a. Concurrently a -> IO a runConcurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (t :: * -> *) m a. (Foldable t, Monoid m) => (a -> m) -> t a -> m F.foldMap(forall a. IO a -> Concurrently a Concurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (f :: * -> *) a. Functor f => f a -> f () voidforall b c a. (b -> c) -> (a -> b) -> a -> c .a -> IO b f )-- | `forConcurrently_` is `forConcurrently` with the return value discarded;-- a concurrent equivalent of 'forM_'.forConcurrently_ ::F.Foldablef =>f a ->(a ->IOb )->IO()forConcurrently_ :: forall (f :: * -> *) a b. Foldable f => f a -> (a -> IO b) -> IO () forConcurrently_ =forall a b c. (a -> b -> c) -> b -> a -> c flipforall (f :: * -> *) a b. Foldable f => (a -> IO b) -> f a -> IO () mapConcurrently_ -- | Perform the action in the given number of threads.---- @since 2.1.1replicateConcurrently ::Int->IOa ->IO[a ]replicateConcurrently :: forall a. Int -> IO a -> IO [a] replicateConcurrently Int cnt =forall a. Concurrently a -> IO a runConcurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (t :: * -> *) (f :: * -> *) a. (Traversable t, Applicative f) => t (f a) -> f (t a) sequenceAforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Int -> a -> [a] replicateInt cnt forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. IO a -> Concurrently a Concurrently -- | Same as 'replicateConcurrently', but ignore the results.---- @since 2.1.1replicateConcurrently_ ::Int->IOa ->IO()replicateConcurrently_ :: forall a. Int -> IO a -> IO () replicateConcurrently_ Int cnt =forall a. Concurrently a -> IO a runConcurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m F.foldforall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. Int -> a -> [a] replicateInt cnt forall b c a. (b -> c) -> (a -> b) -> a -> c .forall a. IO a -> Concurrently a Concurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (f :: * -> *) a. Functor f => f a -> f () void-- ------------------------------------------------------------------------------- | A value of type @Concurrently a@ is an @IO@ operation that can be-- composed with other @Concurrently@ values, using the @Applicative@-- and @Alternative@ instances.---- Calling @runConcurrently@ on a value of type @Concurrently a@ will-- execute the @IO@ operations it contains concurrently, before-- delivering the result of type @a@.---- For example---- > (page1, page2, page3)-- > <- runConcurrently $ (,,)-- > <$> Concurrently (getURL "url1")-- > <*> Concurrently (getURL "url2")-- > <*> Concurrently (getURL "url3")--newtypeConcurrently a =Concurrently {forall a. Concurrently a -> IO a runConcurrently ::IOa }instanceFunctorConcurrently wherefmap :: forall a b. (a -> b) -> Concurrently a -> Concurrently b fmapa -> b f (Concurrently IO a a )=forall a. IO a -> Concurrently a Concurrently forall a b. (a -> b) -> a -> b $a -> b f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>IO a a instanceApplicativeConcurrently wherepure :: forall a. a -> Concurrently a pure=forall a. IO a -> Concurrently a Concurrently forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (m :: * -> *) a. Monad m => a -> m a returnConcurrently IO (a -> b) fs <*> :: forall a b. Concurrently (a -> b) -> Concurrently a -> Concurrently b <*>Concurrently IO a as =forall a. IO a -> Concurrently a Concurrently forall a b. (a -> b) -> a -> b $(\(a -> b f ,a a )->a -> b f a a )forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall a b. IO a -> IO b -> IO (a, b) concurrently IO (a -> b) fs IO a as -- | 'Control.Alternative.empty' waits forever. 'Control.Alternative.<|>' returns the first to finish and 'cancel's the other.instanceAlternativeConcurrently whereempty :: forall a. Concurrently a empty=forall a. IO a -> Concurrently a Concurrently forall a b. (a -> b) -> a -> b $forall (f :: * -> *) a b. Applicative f => f a -> f b forever(Int -> IO () threadDelayforall a. Bounded a => a maxBound)Concurrently IO a as <|> :: forall a. Concurrently a -> Concurrently a -> Concurrently a <|>Concurrently IO a bs =forall a. IO a -> Concurrently a Concurrently forall a b. (a -> b) -> a -> b $forall a c b. (a -> c) -> (b -> c) -> Either a b -> c eitherforall a. a -> a idforall a. a -> a idforall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall a b. IO a -> IO b -> IO (Either a b) race IO a as IO a bs #if MIN_VERSION_base(4,9,0) -- | Only defined by @async@ for @base >= 4.9@---- @since 2.1.0instanceSemigroupa =>Semigroup(Concurrently a )where<> :: Concurrently a -> Concurrently a -> Concurrently a (<>)=forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2forall a. Semigroup a => a -> a -> a (<>)-- | @since 2.1.0instance(Semigroupa ,Monoida )=>Monoid(Concurrently a )wheremempty :: Concurrently a mempty=forall (f :: * -> *) a. Applicative f => a -> f a pureforall a. Monoid a => a memptymappend :: Concurrently a -> Concurrently a -> Concurrently a mappend=forall a. Semigroup a => a -> a -> a (<>) #else -- | @since 2.1.0instanceMonoida=>Monoid(Concurrentlya)wheremempty=purememptymappend=liftA2mappend #endif -- | A value of type @ConcurrentlyE e a@ is an @IO@ operation that can be-- composed with other @ConcurrentlyE@ values, using the @Applicative@ instance.---- Calling @runConcurrentlyE@ on a value of type @ConcurrentlyE e a@ will-- execute the @IO@ operations it contains concurrently, before delivering-- either the result of type @a@, or an error of type @e@ if one of the actions-- returns @Left@.---- | @since 2.2.5newtypeConcurrentlyE e a =ConcurrentlyE {forall e a. ConcurrentlyE e a -> IO (Either e a) runConcurrentlyE ::IO(Eithere a )}instanceFunctor(ConcurrentlyE e )wherefmap :: forall a b. (a -> b) -> ConcurrentlyE e a -> ConcurrentlyE e b fmapa -> b f (ConcurrentlyE IO (Either e a) ea )=forall e a. IO (Either e a) -> ConcurrentlyE e a ConcurrentlyE forall a b. (a -> b) -> a -> b $forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmapa -> b f )IO (Either e a) ea #if MIN_VERSION_base(4,8,0) instanceBifunctorConcurrentlyE wherebimap :: forall a b c d. (a -> b) -> (c -> d) -> ConcurrentlyE a c -> ConcurrentlyE b d bimapa -> b f c -> d g (ConcurrentlyE IO (Either a c) ea )=forall e a. IO (Either e a) -> ConcurrentlyE e a ConcurrentlyE forall a b. (a -> b) -> a -> b $forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap(forall (p :: * -> * -> *) a b c d. Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d bimapa -> b f c -> d g )IO (Either a c) ea #endif instanceApplicative(ConcurrentlyE e )wherepure :: forall a. a -> ConcurrentlyE e a pure=forall e a. IO (Either e a) -> ConcurrentlyE e a ConcurrentlyE forall b c a. (b -> c) -> (a -> b) -> a -> c .forall (m :: * -> *) a. Monad m => a -> m a returnforall b c a. (b -> c) -> (a -> b) -> a -> c .forall (m :: * -> *) a. Monad m => a -> m a returnConcurrentlyE IO (Either e (a -> b)) fs <*> :: forall a b. ConcurrentlyE e (a -> b) -> ConcurrentlyE e a -> ConcurrentlyE e b <*>ConcurrentlyE IO (Either e a) eas =forall e a. IO (Either e a) -> ConcurrentlyE e a ConcurrentlyE forall a b. (a -> b) -> a -> b $forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap(\(a -> b f ,a a )->a -> b f a a )forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$>forall e a b. IO (Either e a) -> IO (Either e b) -> IO (Either e (a, b)) concurrentlyE IO (Either e (a -> b)) fs IO (Either e a) eas #if MIN_VERSION_base(4,9,0) -- | Either the combination of the successful results, or the first failure. instanceSemigroupa =>Semigroup(ConcurrentlyE e a )where<> :: ConcurrentlyE e a -> ConcurrentlyE e a -> ConcurrentlyE e a (<>)=forall (f :: * -> *) a b c. Applicative f => (a -> b -> c) -> f a -> f b -> f c liftA2forall a. Semigroup a => a -> a -> a (<>)instance(Semigroupa ,Monoida )=>Monoid(ConcurrentlyE e a )wheremempty :: ConcurrentlyE e a mempty=forall (f :: * -> *) a. Applicative f => a -> f a pureforall a. Monoid a => a memptymappend :: ConcurrentlyE e a -> ConcurrentlyE e a -> ConcurrentlyE e a mappend=forall a. Semigroup a => a -> a -> a (<>) #endif -- ------------------------------------------------------------------------------ | Fork a thread that runs the supplied action, and if it raises an-- exception, re-runs the action. The thread terminates only when the-- action runs to completion without raising an exception.forkRepeat ::IOa ->IOThreadIdforkRepeat :: forall a. IO a -> IO ThreadId forkRepeat IO a action =forall b. ((forall b. IO b -> IO b) -> IO b) -> IO b maskforall a b. (a -> b) -> a -> b $\forall b. IO b -> IO b restore ->letgo :: IO () go =doEither SomeException a r <-forall a. IO a -> IO (Either SomeException a) tryAll (forall b. IO b -> IO b restore IO a action )caseEither SomeException a r ofLeftSomeException _->IO () go Either SomeException a _->forall (m :: * -> *) a. Monad m => a -> m a return()inIO () -> IO ThreadId forkIOIO () go catchAll ::IOa ->(SomeException->IOa )->IOa catchAll :: forall a. IO a -> (SomeException -> IO a) -> IO a catchAll =forall e a. Exception e => IO a -> (e -> IO a) -> IO a catchtryAll ::IOa ->IO(EitherSomeExceptiona )tryAll :: forall a. IO a -> IO (Either SomeException a) tryAll =forall e a. Exception e => IO a -> IO (Either e a) try-- A version of forkIO that does not include the outer exception-- handler: saves a bit of time when we will be installing our own-- exception handler.{-# INLINErawForkIO #-}rawForkIO ::IO()->IOThreadIdrawForkIO :: IO () -> IO ThreadId rawForkIO (IOState# RealWorld -> (# State# RealWorld, () #) action )=forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a IOforall a b. (a -> b) -> a -> b $\State# RealWorld s ->case(forall a. a -> State# RealWorld -> (# State# RealWorld, ThreadId# #) fork#State# RealWorld -> (# State# RealWorld, () #) action State# RealWorld s )of(#State# RealWorld s1 ,ThreadId# tid #)->(#State# RealWorld s1 ,ThreadId# -> ThreadId ThreadIdThreadId# tid #){-# INLINErawForkOn #-}rawForkOn ::Int->IO()->IOThreadIdrawForkOn :: Int -> IO () -> IO ThreadId rawForkOn (I#Int# cpu )(IOState# RealWorld -> (# State# RealWorld, () #) action )=forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a IOforall a b. (a -> b) -> a -> b $\State# RealWorld s ->case(forall a. Int# -> a -> State# RealWorld -> (# State# RealWorld, ThreadId# #) forkOn#Int# cpu State# RealWorld -> (# State# RealWorld, () #) action State# RealWorld s )of(#State# RealWorld s1 ,ThreadId# tid #)->(#State# RealWorld s1 ,ThreadId# -> ThreadId ThreadIdThreadId# tid #)