@@ -109,13 +109,19 @@ instance MonadAsync m => Applicative (AsyncT m) where
109 pure = return
109 pure = return
110 (<*>) = ap
110 (<*>) = ap
112−-- The current model is to start a new thread for every task. The input is
112+------------------------------------------------------------------------------
113−-- provided at the time of the creation and therefore no synchronization is
113+-- Alternative
114−-- needed compared to a pool of threads contending to get the input from a
114+------------------------------------------------------------------------------
115−-- channel. However the thread creation overhead may be more than the
115+
116−-- synchronization cost?
116+-- Thread pool vs transient threads
118+-- The current model is to start a new thread for every task. The computation
119+-- input is provided at the time of the creation and therefore no
120+-- synchronization is needed compared to a pool of threads contending to get
121+-- the input from a channel. However the thread creation overhead may be more
122+-- than the synchronization cost needed in the case of pool?
118−-- When the task is over the outputs need to be collected and that requires
124+-- When the task is over, the outputs need to be collected and that requires
119-- synchronization irrespective of a thread pool model or per task new thread
125-- synchronization irrespective of a thread pool model or per task new thread
@@ -123,35 +129,6 @@ instance MonadAsync m => Applicative (AsyncT m) where
123-- threads and send them work via a shared channel. When there is no more work
129-- threads and send them work via a shared channel. When there is no more work
124-- available we need a way to close the channel and wakeup all waiters so that
130-- available we need a way to close the channel and wakeup all waiters so that
125-- they can go away rather than waiting indefinitely.
131-- they can go away rather than waiting indefinitely.
128−-- Only those actions that are marked with 'async' are guaranteed to be
129−-- asynchronous. Asyncly is free to run other actions synchronously or
130−-- asynchronously and it should not matter to the semantics of the program, if
131−-- it does then use async to force.
133−-- Why not make async as default and ask the programmer to use a 'sync'
134−-- primitive to force an action to run synchronously? But then we would not
135−-- have the freedom to convert the async actions to sync dynamically. Note that
136−-- it is safe to convert a sync action to async but vice-versa is not true.
137−-- Converting an async to sync can cause change in semantics if the async
138−-- action was an infinite loop for example.
140−-- | In an 'Alternative' composition, force the action to run asynchronously.
141−-- The @\<|\>@ operator implies "can be parallel", whereas 'async' implies
142−-- "must be parallel". Note that outside an 'Alternative' composition 'async'
143−-- is not useful and should not be used. Even in an 'Alternative' composition
144−-- 'async' is not useful as the last action as the last action always runs in
145−-- the current thread.
146−async :: MonadAsync m => AsyncT m a -> AsyncT m a
147−async action = AsyncT $ runAsyncTask True (runAsyncT action)
149−makeAsync :: MonadAsync m => ((a -> m ()) -> m ()) -> AsyncT m a
150−makeAsync = AsyncT . makeCont
152−------------------------------------------------------------------------------
154−------------------------------------------------------------------------------
156instance MonadAsync m => Alternative (AsyncT m) where
133instance MonadAsync m => Alternative (AsyncT m) where
157 {-# SPECIALIZE instance Alternative (AsyncT IO) #-}
134 {-# SPECIALIZE instance Alternative (AsyncT IO) #-}
@@ -278,6 +255,34 @@ infixr 1 >>|
278(>>|) :: MonadAsync m => AsyncT m a -> AsyncT m b -> AsyncT m a
255(>>|) :: MonadAsync m => AsyncT m a -> AsyncT m b -> AsyncT m a
279(>>|) = afterfirst
256(>>|) = afterfirst
258+------------------------------------------------------------------------------
260+------------------------------------------------------------------------------
262+-- Only those actions that are marked with 'async' are guaranteed to be
263+-- asynchronous. Asyncly is free to run other actions synchronously or
264+-- asynchronously and it should not matter to the semantics of the program, if
265+-- it does then use async to force.
267+-- Why not make async as default and ask the programmer to use a 'sync'
268+-- primitive to force an action to run synchronously? But then we would not
269+-- have the freedom to convert the async actions to sync dynamically. Note that
270+-- it is safe to convert a sync action to async but vice-versa is not true.
271+-- Converting an async to sync can cause change in semantics if the async
272+-- action was an infinite loop for example.
274+-- | In an 'Alternative' composition, force the action to run asynchronously.
275+-- The @\<|\>@ operator implies "can be parallel", whereas 'async' implies
276+-- "must be parallel". Note that outside an 'Alternative' composition 'async'
277+-- is not useful and should not be used. Even in an 'Alternative' composition
278+-- 'async' is not useful as the last action as the last action always runs in
279+-- the current thread.
280+async :: MonadAsync m => AsyncT m a -> AsyncT m a
281+async action = AsyncT $ runAsyncTask True (runAsyncT action)
283+makeAsync :: MonadAsync m => ((a -> m ()) -> m ()) -> AsyncT m a
284+makeAsync = AsyncT . makeCont
281------------------------------------------------------------------------------
286------------------------------------------------------------------------------
282-- Controlling thread quota
287-- Controlling thread quota
283------------------------------------------------------------------------------
288------------------------------------------------------------------------------