@@ -9,6 +9,8 @@ module Strands.Threads
@@ -25,7 +27,7 @@ import qualified Control.Exception.Lifted as EL
25import Control.Monad.Catch (MonadCatch, MonadThrow, throwM,
27import Control.Monad.Catch (MonadCatch, MonadThrow, throwM,
27import Control.Monad.IO.Class (MonadIO (..))
29import Control.Monad.IO.Class (MonadIO (..))
28−import Control.Monad.State (get, gets, modify,
30+import Control.Monad.State (get, gets, modify, mzero,
29 runStateT, when, StateT)
31 runStateT, when, StateT)
30import Control.Monad.Trans.Class (MonadTrans (lift))
32import Control.Monad.Trans.Class (MonadTrans (lift))
31import Control.Monad.Trans.Control (MonadBaseControl, liftBaseWith)
33import Control.Monad.Trans.Control (MonadBaseControl, liftBaseWith)
@@ -531,30 +533,23 @@ collectResult r = do
531 liftIO $ atomically $ writeTChan chan
533 liftIO $ atomically $ writeTChan chan
532 (ChildResult (Right (unsafeCoerce r)))
534 (ChildResult (Right (unsafeCoerce r)))
534−-- | Invoked to store the result of the computation in the context and finish
535−-- the computation when the computation is done
536−finishComputation :: MonadIO m => a -> AsyncT m b
537−finishComputation x = AsyncT $ do
541-- XXX pass a collector function and return a Traversable?
536-- XXX pass a collector function and return a Traversable?
542-- XXX Ideally it should be a non-empty list.
537-- XXX Ideally it should be a non-empty list.
544-- | Run an 'AsyncT m' computation and collect the results generated by each
539-- | Run an 'AsyncT m' computation and collect the results generated by each
545-- thread of the computation in a list.
540-- thread of the computation in a list.
546−gather :: forall m a. (MonadIO m, MonadCatch m)
541+waitAsync :: forall m a b. (MonadIO m, MonadCatch m)
547− => AsyncT m a -> m [a]
542+ => (a -> AsyncT m a) -> AsyncT m a -> m [a]
548−gather m = do
543+waitAsync finalizer m = do
549 childChan <- liftIO $ atomically newTChan
544 childChan <- liftIO $ atomically newTChan
550 pendingRef <- liftIO $ newIORef []
545 pendingRef <- liftIO $ newIORef []
551 resultsRef <- liftIO $ newIORef []
546 resultsRef <- liftIO $ newIORef []
552 credit <- liftIO $ newIORef maxBound
547 credit <- liftIO $ newIORef maxBound
554 let ctx = initContext (empty :: AsyncT m a) childChan pendingRef credit
549 let ctx = initContext (empty :: AsyncT m a) childChan pendingRef credit
555− finishComputation resultsRef
550+ finalizer resultsRef
557− r <- try $ runStateT (runAsyncT $ m >>= finishComputation) ctx
552+ r <- try $ runStateT (runAsyncT $ m >>= finalizer) ctx
559 case r of
554 case r of
560 Left (exc :: SomeException) -> do
555 Left (exc :: SomeException) -> do
@@ -565,3 +560,24 @@ gather m = do
565 case e of
560 case e of
566 Just (exc :: SomeException) -> throwM exc
561 Just (exc :: SomeException) -> throwM exc
567 Nothing -> liftIO $ readIORef resultsRef
562 Nothing -> liftIO $ readIORef resultsRef
564+-- | Invoked to store the result of the computation in the context and finish
565+-- the computation when the computation is done
566+gatherResult :: MonadIO m => a -> AsyncT m a
567+gatherResult x = AsyncT $ do
571+-- | Run an 'AsyncT m' computation and collect the results generated by each
572+-- thread of the computation in a list.
573+gather :: forall m a. (MonadIO m, MonadCatch m)
574+ => AsyncT m a -> m [a]
575+gather m = waitAsync gatherResult m
577+-- | Run an 'AsyncT m' computation, wait for it to finish and discard the
579+wait :: forall m a. (MonadIO m, MonadCatch m)
580+ => AsyncT m a -> m ()
582+ _ <- waitAsync (const mzero) m