@@ -23,6 +23,7 @@ import Data.Dynamic (Typeable)
23import Data.IORef
23import Data.IORef
24 (IORef, atomicModifyIORef, readIORef, writeIORef, modifyIORef,
24 (IORef, atomicModifyIORef, readIORef, writeIORef, modifyIORef,
26+import Data.List (delete)
26import Data.Maybe (fromJust)
27import Data.Maybe (fromJust)
27import Control.Monad.IO.Class (MonadIO(..))
28import Control.Monad.IO.Class (MonadIO(..))
28import Control.Monad.State
29import Control.Monad.State
@@ -48,31 +49,31 @@ runCont EventF { xcomp = x, fcomp = fs } = runAsyncT $ do
48-- Thread Management (creation, reaping and killing)
49-- Thread Management (creation, reaping and killing)
49------------------------------------------------------------------------------
50------------------------------------------------------------------------------
51−tryReclaimZombies :: MonadIO m => TChan ThreadId -> IORef [EventF] -> m ()
52+tryReclaimZombies :: MonadIO m => TChan ThreadId -> IORef [ThreadId] -> m ()
52tryReclaimZombies chan pendingRef = do
53tryReclaimZombies chan pendingRef = do
53 pending <- liftIO $ readIORef pendingRef
54 pending <- liftIO $ readIORef pendingRef
54− if length pending == 0
55+ case pending of
55− then return ()
56+ [] -> return ()
57 mtid <- liftIO $ atomically $ tryReadTChan chan
58 mtid <- liftIO $ atomically $ tryReadTChan chan
58 case mtid of
59 case mtid of
59 Nothing -> return ()
60 Nothing -> return ()
60 Just tid -> do
61 Just tid -> do
61− liftIO $ writeIORef pendingRef $ filter (\x -> threadId x /= tid) pending
62+ liftIO $ writeIORef pendingRef $ delete tid pending
62 tryReclaimZombies chan pendingRef
63 tryReclaimZombies chan pendingRef
64−waitForOneChild :: MonadIO m => TChan ThreadId -> IORef [EventF] -> m ()
65+waitForOneChild :: MonadIO m => TChan ThreadId -> IORef [ThreadId] -> m ()
65waitForOneChild chan pendingRef = do
66waitForOneChild chan pendingRef = do
66 -- XXX assert pending must have at least one element
67 -- XXX assert pending must have at least one element
67 -- assert that the tid is found in our list
68 -- assert that the tid is found in our list
68 tid <- liftIO $ atomically $ readTChan chan
69 tid <- liftIO $ atomically $ readTChan chan
69− liftIO $ modifyIORef pendingRef $ filter (\x -> threadId x /= tid)
70+ liftIO $ modifyIORef pendingRef $ delete tid
71-- | kill all the child threads associated with the continuation context
72-- | kill all the child threads associated with the continuation context
72killChildren :: EventF -> IO ()
73killChildren :: EventF -> IO ()
73killChildren ctx = do
74killChildren ctx = do
74 ths <- readIORef (pendingThreads ctx)
75 ths <- readIORef (pendingThreads ctx)
75− mapM_ (killThread . threadId) ths
76+ mapM_ killThread ths
77-- XXX this is not a real semaphore as it does not really block on wait,
78-- XXX this is not a real semaphore as it does not really block on wait,
78-- instead it returns whether the value is zero or non-zero.
79-- instead it returns whether the value is zero or non-zero.
@@ -120,15 +121,15 @@ forkIt current proc = do
120 $ \res -> do
121 $ \res -> do
121 thId <- myThreadId
122 thId <- myThreadId
122 beforeExit child{threadId = thId} res
123 beforeExit child{threadId = thId} res
123− updatePendingThreads current child{threadId = tid}
124+ updatePendingThreads current tid
127− updatePendingThreads :: MonadIO m => EventF -> EventF -> m ()
128+ updatePendingThreads :: MonadIO m => EventF -> ThreadId -> m ()
128− updatePendingThreads cur child = do
129+ updatePendingThreads cur tid = do
129− -- update the new thread first so that if it exited already reclaim
130+ -- update the new thread before reclaiming zombies so that if it exited
130− -- finds it in the list and does not panic.
131+ -- already reclaim finds it in the list and does not panic.
131− liftIO $ modifyIORef (pendingThreads cur) $ (\ts -> child:ts)
132+ liftIO $ modifyIORef (pendingThreads cur) $ (\ts -> tid:ts)
132 tryReclaimZombies (zombieChannel cur) (pendingThreads cur)
133 tryReclaimZombies (zombieChannel cur) (pendingThreads cur)
134 newChildCont cur = do
135 newChildCont cur = do