summaryrefslogtreecommitdiff
path: root/src/Control/Concurrent
diff options
context:
space:
mode:
Diffstat (limited to 'src/Control/Concurrent')
-rw-r--r--src/Control/Concurrent/Lifted/Instrument.hs29
1 files changed, 24 insertions, 5 deletions
diff --git a/src/Control/Concurrent/Lifted/Instrument.hs b/src/Control/Concurrent/Lifted/Instrument.hs
index 9a409569..7e4a7356 100644
--- a/src/Control/Concurrent/Lifted/Instrument.hs
+++ b/src/Control/Concurrent/Lifted/Instrument.hs
@@ -10,6 +10,7 @@ module Control.Concurrent.Lifted.Instrument
10 10
11import qualified Control.Concurrent.Lifted as Raw 11import qualified Control.Concurrent.Lifted as Raw
12import Control.Concurrent.Lifted hiding (fork) 12import Control.Concurrent.Lifted hiding (fork)
13import Control.Exception (fromException)
13import Control.Monad.Trans.Control 14import Control.Monad.Trans.Control
14import System.IO.Unsafe 15import System.IO.Unsafe
15import qualified Data.Map.Strict as Map 16import qualified Data.Map.Strict as Map
@@ -18,6 +19,9 @@ import Control.Monad.Base
18import qualified GHC.Conc as GHC 19import qualified GHC.Conc as GHC
19import Data.Time() 20import Data.Time()
20import Data.Time.Clock 21import Data.Time.Clock
22import System.IO
23import Control.Monad.IO.Class
24
21 25
22data PerThread = PerThread 26data PerThread = PerThread
23 { lbl :: String 27 { lbl :: String
@@ -25,13 +29,15 @@ data PerThread = PerThread
25 } 29 }
26 deriving (Eq,Ord,Show) 30 deriving (Eq,Ord,Show)
27 31
28newtype GlobalState = GlobalState 32data GlobalState = GlobalState
29 { threads :: Map.Map ThreadId PerThread 33 { threads :: !(Map.Map ThreadId PerThread)
34 , reportException :: String -> IO ()
30 } 35 }
31 36
32globals :: MVar GlobalState 37globals :: MVar GlobalState
33globals = unsafePerformIO $ newMVar $ GlobalState 38globals = unsafePerformIO $ newMVar $ GlobalState
34 { threads = Map.empty 39 { threads = Map.empty
40 , reportException = hPutStrLn stderr
35 } 41 }
36{-# NOINLINE globals #-} 42{-# NOINLINE globals #-}
37 43
@@ -40,14 +46,27 @@ forkIO :: IO () -> IO ThreadId
40forkIO = fork 46forkIO = fork
41{-# INLINE forkIO #-} 47{-# INLINE forkIO #-}
42 48
43fork :: MonadBaseControl IO m => m () -> m ThreadId 49fork :: (MonadBaseControl IO m, MonadIO m) => m () -> m ThreadId
44fork action = do 50fork action = do
45 t <- Raw.fork $ do 51 t <- Raw.fork $ do
46 tid <- myThreadId 52 tid <- myThreadId
47 tm <- liftBase getCurrentTime 53 tm <- liftBase getCurrentTime
48 bracket_ (modifyThreads $! Map.insert tid (PerThread "" tm)) 54 bracket_ (modifyThreads $! Map.insert tid (PerThread "" tm))
49 (modifyThreads $! Map.delete tid) 55 (return ())
50 action 56 $ do catch action $ \e -> case fromException e of
57 Just ThreadKilled -> return ()
58 Nothing -> liftIO $ do
59 g <- takeMVar globals
60 let l = concat [ show e
61 , " ("
62 , maybe "" lbl $ Map.lookup tid (threads g)
63 , ")"
64 ]
65 reportException g l
66 putMVar globals $! g { threads = Map.insert tid (PerThread l tm) $ threads g }
67 throwIO e
68 -- Remove the thread only if it terminated normally or was killed.
69 modifyThreads $! Map.delete tid
51 return t 70 return t
52 71
53labelThread :: ThreadId -> String -> IO () 72labelThread :: ThreadId -> String -> IO ()