@@ -12,11 +12,9 @@
12module Duct.AsyncT
12module Duct.AsyncT
13 ( AsyncT (..)
13 ( AsyncT (..)
14 , waitAsync
14 , waitAsync
17 , onNothing
16 , onNothing
18 , RemoteStatus (..)
17 , RemoteStatus (..)
20 , waitForChildren
18 , waitForChildren
@@ -44,13 +42,10 @@ import Data.Maybe (isJust, isNothing)
44import Unsafe.Coerce (unsafeCoerce)
42import Unsafe.Coerce (unsafeCoerce)
46import Duct.Event
44import Duct.Event
49-- import Debug.Trace
46-- import Debug.Trace
51−type StateM m = StateT EventF m
53−newtype AsyncT m a = AsyncT { runAsyncT :: StateM m (Maybe a) }
48+newtype AsyncT m a = AsyncT { runAsyncT :: StateT EventF m (Maybe a) }
55------------------------------------------------------------------------------
50------------------------------------------------------------------------------
56-- Remote data types
51-- Remote data types
@@ -89,6 +84,7 @@ instance Monad (AsyncT m) => Functor (AsyncT m) where
89-- Applicative
84-- Applicative
90------------------------------------------------------------------------------
85------------------------------------------------------------------------------
92-- | Warning: Radically untyped stuff. handle with care
88-- | Warning: Radically untyped stuff. handle with care
93getContinuations :: Monad m => StateM m [a -> AsyncT m b]
89getContinuations :: Monad m => StateM m [a -> AsyncT m b]
94getContinuations = do
90getContinuations = do
@@ -109,6 +105,8 @@ restoreStack :: MonadState EventF m => t -> m ()
109restoreStack fs = modify $ \EventF {..} ->
105restoreStack fs = modify $ \EventF {..} ->
110 EventF { event = Nothing, fcomp = (unsafeCoerce fs), .. }
106 EventF { event = Nothing, fcomp = (unsafeCoerce fs), .. }
112instance Monad m => Applicative (AsyncT m) where
110instance Monad m => Applicative (AsyncT m) where
113 pure a = AsyncT . return $ Just a
111 pure a = AsyncT . return $ Just a
114 m1 <*> m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
112 m1 <*> m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
@@ -145,24 +143,29 @@ tailsafe (_:xs) = xs
146instance Monad m => Monad (AsyncT m) where
144instance Monad m => Monad (AsyncT m) where
147 return = pure
145 return = pure
148− m >>= f = AsyncT $ do
149− -- save m in xcomp and add f to the head of fcomp
150− -- _ <- setEventCont m f
151− modify $ \EventF { fcomp = fs, .. } ->
152− EventF { xcomp = unsafeCoerce m, fcomp = unsafeCoerce f : fs, .. }
154− -- run m under this modified environment
147+ m >>= f = AsyncT $ do
148+ -- Save the 'm' and 'f', in case we migrate to a new thread before this
149+ -- bind operation completes, we run the operation manually in the new
151+ modify $ \EventF { fstack = fs, .. } ->
152+ EventF { currentm = unsafeCoerce m
153+ , fstack = unsafeCoerce f : fs
156+ -- Inner bind operations in 'm' add their 'f' to fstack. If we migrate to
157+ -- a new thread somewhere in the middle we unwind the fstack and run these
158+ -- functions manually after migration.
155 mres <- runAsyncT m
159 mres <- runAsyncT m
156− -- remove the head of fcomp apply it to mres and that becomes the new xcomp.
160+
157− -- is head of fcomp always the same as f?
158 let res = case mres of
161 let res = case mres of
159 Nothing -> empty
162 Nothing -> empty
160 Just x -> f x
163 Just x -> f x
162− -- XXX why would we have more than one continuation? Can we have just one
163− -- instead of a list and remove it after every bind?
164− modify $ \EventF { fcomp = fs, .. } ->
165+ modify $ \EventF { fstack = fs, .. } ->
165− EventF { xcomp = unsafeCoerce res, fcomp = tailsafe fs, .. }
166+ EventF { currentm = unsafeCoerce res
167+ , fstack = tailsafe fs
167 runAsyncT res
170 runAsyncT res
@@ -178,15 +181,11 @@ instance (Monoid a, Monad (AsyncT m)) => Monoid (AsyncT m a) where
178-- Backtracking
181-- Backtracking
179------------------------------------------------------------------------------
182------------------------------------------------------------------------------
181-- | Run the closure (the 'x' in 'x >>= f') of the current bind operation.
185-- | Run the closure (the 'x' in 'x >>= f') of the current bind operation.
182runClosure :: EventF -> StateM m (Maybe a)
186runClosure :: EventF -> StateM m (Maybe a)
183runClosure EventF { xcomp = x } = runAsyncT (unsafeCoerce x)
187runClosure EventF { xcomp = x } = runAsyncT (unsafeCoerce x)
185−-- | Compose a list of continuations.
186−compose :: MonadIO m => [a -> AsyncT m a] -> (a -> AsyncT m b)
187−compose [] = const empty
188−compose (f:fs) = \x -> f x >>= compose fs
190-- | Run the continuation (the 'f' in 'x >>= f') of the current bind operation with the current state.
189-- | Run the continuation (the 'f' in 'x >>= f') of the current bind operation with the current state.
191runContinuation :: MonadIO m => EventF -> a -> StateM m (Maybe b)
190runContinuation :: MonadIO m => EventF -> a -> StateM m (Maybe b)
192runContinuation EventF { fcomp = fs } =
191runContinuation EventF { fcomp = fs } =
@@ -226,18 +225,14 @@ back reason = AsyncT $ do
226 Nothing -> runContinuation first x
225 Nothing -> runContinuation first x
227 justreason -> goBackt $ Backtrack justreason bs
226 justreason -> goBackt $ Backtrack justreason bs
229------------------------------------------------------------------------------
230------------------------------------------------------------------------------
230-- MonadIO
231-- MonadIO
231------------------------------------------------------------------------------
232------------------------------------------------------------------------------
233instance MonadIO m => MonadIO (AsyncT m) where
234instance MonadIO m => MonadIO (AsyncT m) where
235− ex <- liftIO' $ (mx >>= return . Right) `catch`
236− (\(e :: SomeException) -> return $ Left e)
240− where liftIO' x = AsyncT $ liftIO x >>= return . Just
235+ liftIO mx = AsyncT $ liftIO mx >>= return . Just
242-------------------------------------------------------------------------------
237-------------------------------------------------------------------------------
243-- AsyncT transformer
238-- AsyncT transformer
@@ -403,6 +398,7 @@ instance (Num a, Monad (AsyncT m)) => Num (AsyncT m a) where
403 abs f = f >>= return . abs
398 abs f = f >>= return . abs
404 signum f = f >>= return . signum
399 signum f = f >>= return . signum
406class AdditionalOperators m where
402class AdditionalOperators m where
408 -- | Run @m a@ discarding its result before running @m b@.
404 -- | Run @m a@ discarding its result before running @m b@.
@@ -469,3 +465,12 @@ infixr 1 <***, <**, **>
469 runAsyncT mb
465 runAsyncT mb
470 return $ Just x
466 return $ Just x
470+(<**) :: Monad m => AsyncT m a -> AsyncT m b -> AsyncT m a
471+(<**) ma mb = AsyncT $ do