Reputation: 3072
When I print something in Java, I usually append the name of the thread to the print statement so I know what thread is running what print statement. How do I get and set the thread name in Haskell? If I can't set the thread name, how do I make a thread that has a given name?
Note: I usually give my threads descriptive names like "GUI_thread", "main_thread", "database_thread", etc
Upvotes: 4
Views: 535
Reputation: 52280
As I said in a comment you can use labelThread
to give the thread a label. Sadly I could not find a way to pull this label back out (all I found was this invalid ticket where someone wanted to do just this).
But as descriped in Parallel and Concurrent Programming in Haskell you can get an event-log view on this:
(straight from there – I hope nobody minds):
main = do
t <- myThreadId
labelThread t "main"
m <- newEmptyMVar
t <- forkIO $ putMVar m 'a'
labelThread t "a"
t <- forkIO $ putMVar m 'b'
labelThread t "b"
traceEventIO "before takeMVar"
takeMVar m
takeMVar m
You then should compile it with the threaded
and eventlog
switches set:
ghc mvar4.hs -threaded -eventlog
and can call it with +RTS
and -l
:
./mvar4 +RTS -l
Finally you can look at the output with ghc-evetns
:
ghc-events show mvar4.eventlog
That seems not to be exactly what you want, so here is a (very basic) example of how you could do it yourself (using just lists and an MVar
to keep the association between the ThreadId
and its name):
import Control.Concurrent
type Labels = MVar [(ThreadId, String)]
initLabels :: IO Labels
initLabels = newMVar []
labelThread :: Labels -> ThreadId -> String -> IO ()
labelThread labels threadId label =
modifyMVar_ labels (\assocs -> return $ (threadId, label):assocs)
getLabel :: Labels -> ThreadId -> IO String
getLabel labels threadId = withMVar labels (\assocs ->
case lookup threadId assocs of
Just label -> return label
Nothing -> return $ show threadId)
and you can use it like this:
main :: IO ()
main = do
ls <- initLabels
myId <- myThreadId
getLabel ls myId >>= print
labelThread ls myId "my Thread"
getLabel ls myId >>= print
which would get you:
λ> :main
"ThreadId 50"
"my Thread"
Obviously this might not be a good idea if you create lots of threads. At the very least you should add something to remove the label again at the end of your thread:
removeLabel :: Labels -> ThreadId -> IO ()
removeLabel labels threadId =
modifyMVar_ labels (return . filter ((/= threadId) . fst))
forkLabeledIO :: Labels -> String -> IO () -> IO ThreadId
forkLabeledIO labels label computation = forkIO $ do
myId <- myThreadId
labelThread labels myId label
computation
removeLabel labels myId
... yeah I know: nasty – and of course a Map
might be a better idea too – but I hope you get the basic idea
Upvotes: 5