1{-# LANGUAGE UndecidableInstances #-}
7 -- * Asynchronous actions
10 , async, asyncBound, asyncOn
11 , asyncWithUnmask, asyncOnWithUnmask
13 -- ** Spawning with automatic 'cancel'ation
14 , withAsync, withAsyncBound, withAsyncOn
15 , withAsyncWithUnmask, withAsyncOnWithUnmask
17 -- ** Quering 'Async's
18 , wait, poll, waitCatch
20 , uninterruptibleCancel
23 , A.AsyncCancelled(..)
26 , A.waitSTM, A.pollSTM, A.waitCatchSTM
28 -- ** Waiting for multiple 'Async's
29 , waitAny, waitAnyCatch, waitAnyCancel, waitAnyCatchCancel
30 , waitEither, waitEitherCatch, waitEitherCancel, waitEitherCatchCancel
34 -- ** Waiting for multiple 'Async's in STM
38 , A.waitEitherCatchSTM
44 , A.ExceptionInLinkedThread(..)
46 -- * Convenient utilities
47 , race, race_, concurrently, concurrently_
48 , mapConcurrently, mapConcurrently_
49 , forConcurrently, forConcurrently_
50 , replicateConcurrently, replicateConcurrently_
56import Control.Applicative
57import Control.Concurrent (threadDelay)
58import Control.Concurrent.Async (Async)
59import Control.Exception (Exception, SomeException)
60import Control.Monad (forever, void)
61import Data.Foldable (fold)
62import qualified Control.Concurrent.Async as A
64import Effectful.Internal.Effect
65import Effectful.Internal.Env
66import Effectful.Internal.Monad
68-- | Run 'Eff' computations asynchronously using the @async@ library.
70-- /Note:/ thread local state changes in 'Eff' computations lifted into an
71-- 'Async' will not affect the parent thread.
72data AsyncE :: Effect where
75runAsyncE :: IOE :> es => Eff (AsyncE : es) a -> Eff es a
76runAsyncE = evalEffect (IdE AsyncE)
78-- | Generalized version of 'A.async'.
79async :: AsyncE :> es => Eff es a -> Eff es (Async a)
80async = liftAsync A.async
82-- | Generalized version of 'A.asyncBound'.
83asyncBound :: AsyncE :> es => Eff es a -> Eff es (Async a)
84asyncBound = liftAsync A.asyncBound
86-- | Generalized version of 'A.asyncOn'.
87asyncOn :: AsyncE :> es => Int -> Eff es a -> Eff es (Async a)
88asyncOn cpu = liftAsync (A.asyncOn cpu)
90-- | Generalized version of 'A.asyncWithUnmask'.
93 => ((forall b. Eff es b -> Eff es b) -> Eff es a)
95asyncWithUnmask = liftAsyncWithUnmask A.asyncWithUnmask
97-- | Generalized version of 'A.asyncOnWithUnmask'.
101 -> ((forall b. Eff es b -> Eff es b) -> Eff es a)
103asyncOnWithUnmask cpu = liftAsyncWithUnmask (A.asyncOnWithUnmask cpu)
105-- | Generalized version of 'A.withAsync'.
109 -> (Async a -> Eff es b)
111withAsync = liftWithAsync A.withAsync
113-- | Generalized version of 'A.withAsyncBound'.
117 -> (Async a -> Eff es b)
119withAsyncBound = liftWithAsync A.withAsyncBound
121-- | Generalized version of 'A.withAsyncOn'.
126 -> (Async a -> Eff es b)
128withAsyncOn cpu = liftWithAsync (A.withAsyncOn cpu)
130-- | Generalized version of 'A.withAsyncWithUnmask'.
133 => ((forall c. Eff es c -> Eff es c) -> Eff es a)
134 -> (Async a -> Eff es b)
136withAsyncWithUnmask = liftWithAsyncWithUnmask A.withAsyncWithUnmask
138-- | Generalized version of 'A.withAsyncOnWithUnmask'.
142 -> ((forall c. Eff es c -> Eff es c) -> Eff es a)
143 -> (Async a -> Eff es b)
145withAsyncOnWithUnmask cpu = liftWithAsyncWithUnmask (A.withAsyncOnWithUnmask cpu)
147-- | Generalized version of 'A.wait'.
148wait :: AsyncE :> es => Async a -> Eff es a
149wait = unsafeEff_ . A.wait
151-- | Generalized version of 'A.poll'.
155 -> Eff es (Maybe (Either SomeException a))
156poll = unsafeEff_ . A.poll
158-- | Generalized version of 'A.cancel'.
159cancel :: AsyncE :> es => Async a -> Eff es ()
160cancel = unsafeEff_ . A.cancel
162-- | Generalized version of 'A.cancelWith'.
163cancelWith :: (Exception e, AsyncE :> es) => Async a -> e -> Eff es ()
164cancelWith a = unsafeEff_ . A.cancelWith a
166-- | Generalized version of 'A.uninterruptibleCancel'.
167uninterruptibleCancel :: AsyncE :> es => Async a -> Eff es ()
168uninterruptibleCancel = unsafeEff_ . A.uninterruptibleCancel
170-- | Generalized version of 'A.waitCatch'.
174 -> Eff es (Either SomeException a)
175waitCatch = unsafeEff_ . A.waitCatch
177-- | Generalized version of 'A.waitAny'.
178waitAny :: AsyncE :> es => [Async a] -> Eff es (Async a, a)
179waitAny = unsafeEff_ . A.waitAny
181-- | Generalized version of 'A.waitAnyCatch'.
185 -> Eff es (Async a, Either SomeException a)
186waitAnyCatch = unsafeEff_ . A.waitAnyCatch
188-- | Generalized version of 'A.waitAnyCancel'.
189waitAnyCancel :: AsyncE :> es => [Async a] -> Eff es (Async a, a)
190waitAnyCancel = unsafeEff_ . A.waitAnyCancel
192-- | Generalized version of 'A.waitAnyCatchCancel'.
196 -> Eff es (Async a, Either SomeException a)
197waitAnyCatchCancel = unsafeEff_ . A.waitAnyCatchCancel
199-- | Generalized version of 'A.waitEither'.
204 -> Eff es (Either a b)
205waitEither a b = unsafeEff_ $ A.waitEither a b
207-- | Generalized version of 'A.waitEitherCatch'.
212 -> Eff es (Either (Either SomeException a) (Either SomeException b))
213waitEitherCatch a b = unsafeEff_ $ A.waitEitherCatch a b
215-- | Generalized version of 'A.waitEitherCancel'.
220 -> Eff es (Either a b)
221waitEitherCancel a b = unsafeEff_ $ A.waitEitherCancel a b
223-- | Generalized version of 'A.waitEitherCatchCancel'.
228 -> Eff es (Either (Either SomeException a) (Either SomeException b))
229waitEitherCatchCancel a b = unsafeEff_ $ A.waitEitherCatch a b
231-- | Generalized version of 'A.waitEither_'.
232waitEither_ :: AsyncE :> es => Async a -> Async b -> Eff es ()
233waitEither_ a b = unsafeEff_ $ A.waitEither_ a b
235-- | Generalized version of 'A.waitBoth'.
236waitBoth :: AsyncE :> es => Async a -> Async b -> Eff es (a, b)
237waitBoth a b = unsafeEff_ $ A.waitBoth a b
239-- | Generalized version of 'A.link'.
240link :: AsyncE :> es => Async a -> Eff es ()
241link = unsafeEff_ . A.link
243-- | Generalized version of 'A.link2'.
244link2 :: AsyncE :> es => Async a -> Async b -> Eff es ()
245link2 a b = unsafeEff_ $ A.link2 a b
247-- | Generalized version of 'A.race'.
248race :: AsyncE :> es => Eff es a -> Eff es b -> Eff es (Either a b)
249race ma mb = withAsync ma $ \a -> withAsync mb $ \b -> waitEither a b
251-- | Generalized version of 'A.race_'.
252race_ :: AsyncE :> es => Eff es a -> Eff es b -> Eff es ()
253race_ ma mb = withAsync ma $ \a -> withAsync mb $ \b -> waitEither_ a b
255-- | Generalized version of 'A.concurrently'.
256concurrently :: AsyncE :> es => Eff es a -> Eff es b -> Eff es (a, b)
257concurrently ma mb = withAsync ma $ \a -> withAsync mb $ \b -> waitBoth a b
259-- | Generalized version of 'A.concurrently_'.
260concurrently_ :: AsyncE :> es => Eff es a -> Eff es b -> Eff es ()
261concurrently_ ma mb = void $ concurrently ma mb
263-- | Generalized version of 'A.mapConcurrently'.
265 :: (Traversable f, AsyncE :> es)
269mapConcurrently f = runConcurrently . traverse (Concurrently . f)
271-- | Generalized version of 'A.mapConcurrently_'.
273 :: (Foldable f, AsyncE :> es)
277mapConcurrently_ f = runConcurrently . foldMap (Concurrently . void . f)
279-- | Generalized version of 'A.forConcurrently'.
281 :: (Traversable f, AsyncE :> es)
285forConcurrently = flip mapConcurrently
287-- | Generalized version of 'A.forConcurrently_'.
289 :: (Foldable f, AsyncE :> es)
293forConcurrently_ = flip mapConcurrently_
295-- | Generalized version of 'A.replicateConcurrently'.
296replicateConcurrently :: AsyncE :> es => Int -> Eff es a -> Eff es [a]
297replicateConcurrently n =
298 runConcurrently . sequenceA . replicate n . Concurrently
300-- | Generalized version of 'A.replicateConcurrently_'.
301replicateConcurrently_ :: AsyncE :> es => Int -> Eff es a -> Eff es ()
302replicateConcurrently_ n =
303 runConcurrently . fold . replicate n . Concurrently . void
305----------------------------------------
307-- | Generalized version of 'A.Concurrently'.
308newtype Concurrently es a = Concurrently { runConcurrently :: Eff es a }
310instance Functor (Concurrently es) where
311 fmap f (Concurrently a) = Concurrently (fmap f a)
313instance AsyncE :> es => Applicative (Concurrently es) where
314 pure = Concurrently . pure
315 Concurrently fs <*> Concurrently as =
316 Concurrently ((\(f, a) -> f a) <$> concurrently fs as)
318instance AsyncE :> es => Alternative (Concurrently es) where
319 empty = Concurrently . unsafeEff_ . forever $ threadDelay maxBound
320 Concurrently as <|> Concurrently bs =
321 Concurrently (either id id <$> race as bs)
323instance (AsyncE :> es, Semigroup a) => Semigroup (Concurrently es a) where
326instance (AsyncE :> es, Monoid a) => Monoid (Concurrently es a) where
329----------------------------------------
333 :: (IO a -> IO (Async a))
336liftAsync fork action = unsafeEff $ \es0 -> do
338 fork $ unEff action es
341 :: (((forall b. IO b -> IO b) -> IO a) -> IO (Async a))
342 -> ((forall b. Eff es b -> Eff es b) -> Eff es a)
344liftAsyncWithUnmask fork action = unsafeEff $ \es0 -> do
346 fork $ \unmask -> unEff (action $ \m -> unsafeEff $ unmask . unEff m) es
349 :: (IO a -> (Async a -> IO b) -> IO b)
351 -> (Async a -> Eff es b)
353liftWithAsync withA action k = unsafeEff $ \es0 -> do
355 withA (unEff action es)
356 (\a -> unEff (k a) es0)
358liftWithAsyncWithUnmask
359 :: (((forall c. IO c -> IO c) -> IO a) -> (Async a -> IO b) -> IO b)
360 -> ((forall c. Eff es c -> Eff es c) -> Eff es a)
361 -> (Async a -> Eff es b)
363liftWithAsyncWithUnmask withA action k = unsafeEff $ \es0 -> do
365 withA (\unmask -> unEff (action $ \m -> unsafeEff $ unmask . unEff m) es)
366 (\a -> unEff (k a) es0)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list