@@ -22,19 +22,21 @@
23module Asyncly.AsyncT
23module Asyncly.AsyncT
24 ( AsyncT (..)
24 ( AsyncT (..)
25− , Step (..)
25+ -- , Step (..)
30-- , makeAsync
30-- , makeAsync
34 , thereafter
35 , thereafter
36 , afterfirst
37 , afterfirst
39 -- internal
41 -- internal
@@ -42,6 +44,7 @@ module Asyncly.AsyncT
44import Control.Applicative (Alternative (..))
46import Control.Applicative (Alternative (..))
47+import Data.Maybe (maybe)
45import Control.Monad (ap, mzero, when)
48import Control.Monad (ap, mzero, when)
46import Control.Monad.Base (MonadBase (..), liftBaseDefault)
49import Control.Monad.Base (MonadBase (..), liftBaseDefault)
47import Control.Monad.Catch (MonadThrow, throwM)
50import Control.Monad.Catch (MonadThrow, throwM)
@@ -61,8 +64,15 @@ import Control.Monad.Trans.Recorder (MonadRecorder(..))
62import Asyncly.Threads (MonadAsync, Context)
65import Asyncly.Threads (MonadAsync, Context)
64−data Step a m = Stop | Yield a (AsyncT m a)
67+-- data Step a m = Stop | Yield a (AsyncT m a)
65−newtype AsyncT m a = AsyncT { runAsyncT :: m (Step a m) }
68+-- newtype AsyncT m a = AsyncT { runAsyncT :: m (Step a m) }
69+-- stop value is needed for Alternative instance
70+newtype AsyncT m a = AsyncT {
71+ runAsyncT :: forall r.
73+ -> (a -> Maybe (AsyncT m a) -> m r)
67------------------------------------------------------------------------------
77------------------------------------------------------------------------------
68-- Utilities
78-- Utilities
@@ -78,36 +88,33 @@ dbg _ = return ()
79------------------------------------------------------------------------------
89------------------------------------------------------------------------------
81−stop :: Monad m => AsyncT m a
91+-- XXX need to wait for the async threads in case of a stop is returned due to
82−stop = AsyncT . return $ Stop
92+-- async thread spawning.
85−{-# SPECIALIZE parallel
86− :: AsyncT (StateT Context IO) a
87− -> AsyncT (StateT Context IO) a
88− -> StateT Context IO (Step a (StateT Context IO)) #-}
89{-# SPECIALIZE parallel
93{-# SPECIALIZE parallel
90 :: AsyncT IO a
94 :: AsyncT IO a
91 -> AsyncT IO a
95 -> AsyncT IO a
92− -> IO (Step a IO) #-}
96+ -> AsyncT IO a #-}
97+{-# INLINE parallel #-}
93−parallel :: Monad m => AsyncT m a -> AsyncT m a -> m (Step a m)
98+parallel :: Monad m => AsyncT m a -> AsyncT m a -> AsyncT m a
94−parallel ma mb = do
99+parallel (AsyncT m1) m2 = AsyncT $ \stp yld ->
95− runAsyncT ma >>= \step ->
100+ m1 ((runAsyncT m2) stp yld) (\a ax ->
96− case step of
101+ case ax of
98− Yield a mx -> return (Yield a (AsyncT (parallel mx mb)))
102+ Just mx -> yld a (Just (parallel mx m2))
103+ Nothing -> yld a (Just m2)
100instance MonadAsync m => Monad (AsyncT m) where
106instance MonadAsync m => Monad (AsyncT m) where
101− {-# SPECIALIZE instance Monad (AsyncT (StateT Context IO)) #-}
107+ -- {-# SPECIALIZE instance Monad (AsyncT (StateT Context IO)) #-}
102 {-# SPECIALIZE instance Monad (AsyncT IO) #-}
108 {-# SPECIALIZE instance Monad (AsyncT IO) #-}
103− return a = AsyncT . return $ Yield a stop
109+ return a = AsyncT $ \_ yld -> yld a Nothing
105− -- {-# INLINE (>>=) #-}
111+ {-# INLINE (>>=) #-}
106− m >>= f = AsyncT $ do
112+ AsyncT m >>= f = AsyncT $ \stp yld ->
107− runAsyncT m >>= \step ->
113+ m stp (\a ma ->
108− case step of
114+ case ma of
109− Stop -> return Stop -- XXX need to wait for the child threads
115+ Just mx -> (runAsyncT (parallel (f a) (mx >>= f))) stp yld
110− Yield a ma -> runAsyncT $ (f a) <|> (ma >>= f)
116+ Nothing -> (runAsyncT (f a)) stp yld
112------------------------------------------------------------------------------
119------------------------------------------------------------------------------
113-- Functor
120-- Functor
@@ -146,15 +153,16 @@ instance MonadAsync m => Applicative (AsyncT m) where
146-- they can go away rather than waiting indefinitely.
153-- they can go away rather than waiting indefinitely.
148instance MonadAsync m => Alternative (AsyncT m) where
155instance MonadAsync m => Alternative (AsyncT m) where
149− {-# SPECIALIZE instance Alternative (AsyncT (StateT Context IO)) #-}
156+ -- {-# SPECIALIZE instance Alternative (AsyncT (StateT Context IO)) #-}
150 {-# SPECIALIZE instance Alternative (AsyncT IO) #-}
157 {-# SPECIALIZE instance Alternative (AsyncT IO) #-}
151− empty = stop
158+ empty = AsyncT $ \stp _ -> stp
152− (<|>) m1 m2 = AsyncT $ parallel m1 m2
159+ (<|>) m1 m2 = parallel m1 m2
154instance MonadAsync m => MonadPlus (AsyncT m) where
161instance MonadAsync m => MonadPlus (AsyncT m) where
155 mzero = empty
162 mzero = empty
156 mplus = (<|>)
163 mplus = (<|>)
158instance (Monoid a, MonadAsync m) => Monoid (AsyncT m a) where
166instance (Monoid a, MonadAsync m) => Monoid (AsyncT m a) where
159 mappend x y = mappend <$> x <*> y
167 mappend x y = mappend <$> x <*> y
160 mempty = return mempty
168 mempty = return mempty
@@ -171,12 +179,13 @@ instance (Num a, Monad (AsyncT m)) => Num (AsyncT m a) where
171 abs f = f >>= return . abs
179 abs f = f >>= return . abs
172 signum f = f >>= return . signum
180 signum f = f >>= return . signum
174-------------------------------------------------------------------------------
183-------------------------------------------------------------------------------
175-- AsyncT transformer
184-- AsyncT transformer
176-------------------------------------------------------------------------------
185-------------------------------------------------------------------------------
178instance MonadTrans AsyncT where
187instance MonadTrans AsyncT where
179− lift mx = AsyncT $ mx >>= return . (\a -> (Yield a stop))
188+ lift mx = AsyncT $ \_ yld -> mx >>= (\a -> (yld a Nothing))
181instance (MonadBase b m, MonadAsync m) => MonadBase b (AsyncT m) where
190instance (MonadBase b m, MonadAsync m) => MonadBase b (AsyncT m) where
182 liftBase = liftBaseDefault
191 liftBase = liftBaseDefault
@@ -226,6 +235,7 @@ instance (MonadAsync m, MonadRecorder m) => MonadRecorder (AsyncT m) where
226-- Special compositions
235-- Special compositions
227------------------------------------------------------------------------------
236------------------------------------------------------------------------------
229-- | Run @m a@ before running @m b@. The result of @m a@ is discarded.
239-- | Run @m a@ before running @m b@. The result of @m a@ is discarded.
230before :: MonadAsync m => AsyncT m a -> AsyncT m b -> AsyncT m b
240before :: MonadAsync m => AsyncT m a -> AsyncT m b -> AsyncT m b
231before ma mb = AsyncT $ do
241before ma mb = AsyncT $ do
@@ -264,6 +274,7 @@ infixr 1 >>|
264-- | Same as 'afterfirst'.
274-- | Same as 'afterfirst'.
265(>>|) :: MonadAsync m => AsyncT m a -> AsyncT m b -> AsyncT m a
275(>>|) :: MonadAsync m => AsyncT m a -> AsyncT m b -> AsyncT m a
266(>>|) = afterfirst
276(>>|) = afterfirst
268------------------------------------------------------------------------------
279------------------------------------------------------------------------------
269-- Async primitives
280-- Async primitives
@@ -295,17 +306,9 @@ makeAsync :: MonadAsync m => ((a -> m ()) -> m ()) -> AsyncT m a
295makeAsync = AsyncT . makeCont
306makeAsync = AsyncT . makeCont
298−{-# SPECIALIZE waitA_ :: AsyncT IO a -> IO () #-}
309+-- {-# SPECIALIZE waitA_ :: AsyncT IO a -> IO () #-}
299waitA_ :: (MonadAsync m) => AsyncT m a -> m ()
310waitA_ :: (MonadAsync m) => AsyncT m a -> m ()
300−waitA_ (AsyncT m) = run m
311+waitA_ (AsyncT m) = m (return ()) (\_ r -> maybe (return ()) waitA_ r)
306− Yield _ r -> run (runAsyncT r)
307− -- XXX pull from children here
311waitA :: forall m a. (MonadAsync m, MonadCatch m) => AsyncT m a -> m [a]
314waitA :: forall m a. (MonadAsync m, MonadCatch m) => AsyncT m a -> m [a]
@@ -321,6 +324,8 @@ waitA (AsyncT m) = run m
323-- scatter
326-- scatter
327+-- XXX unthreaded case can be more efficient by yielding continuously rather
328+-- than folding a yield followed by Nothing in the parallel case.
324{-# SPECIALIZE eachA :: [a] -> AsyncT IO a #-}
329{-# SPECIALIZE eachA :: [a] -> AsyncT IO a #-}
325eachA :: (MonadIO m, MonadBaseControl IO m, MonadThrow m)
330eachA :: (MonadIO m, MonadBaseControl IO m, MonadThrow m)
326 => [a] -> AsyncT m a
331 => [a] -> AsyncT m a