[Haskell-cafe] How to redirect a handle within a thread (GHC 6.4.1
runtime)?
Benjamin Franksen
benjamin.franksen at bessy.de
Wed Jan 18 14:59:28 EST 2006
On Wednesday 18 January 2006 19:01, Dimitry Golubovsky wrote:
> Is it possible to redirect a Handle (say stdout) somewhere only
> within a running thread (started with forkIO) not touching the same
> handle for the main and other threads?
>
> I have a lot of code written with putStr(Ln) which was used in a
> program acting as a filter, i. e. stdout was redirected by the
> invoking shell. Now I want to run this code within a thread in other
> program, but output must go to a file (or a pipe, or anywhere else a
> file descriptor may be opened for). So fdToHandle is not good because
> I need to modify the `stdout' only for that thread, not to create a
> new Handle. Rewriting the code is not a convenient way (but will be
> done if nothing else helps) because then I will need to pass that
> handle around.
Isn't this _the_ real-world example perfectly matching Robert Dockins'
'threadlocal' proposal?
Anyway, I think you could hack your way around the problem:
{-# NOINLINE special_tid_var #-}
special_tid_var :: MVar ThreadId
special_tid_var = unsafePeformIO newEmptyMVar
{-# NOINLINE special_stdout_var #-}
special_stdout_var :: MVar Handle
special_stdout_var = unsafePeformIO newEmptyMVar
main = do
...
open File ... >>= putMVar special_stdout_var
forkIO ... >>= putMVar special_tid_var
...
-- replacement for the usual putStrLn
putStrLn :: String -> IO ()
putStrLn str = do
mytid <- myThreadId
special_tid <- readMVar special_tid_var
specia_stdout <- readMVar special_stdout_var
if mytid == special_tid
then System.IO.hPutStrLn special_stdout str
else System.IO.putStrLn str
Not tested, but you should get the idea. Caveat: you must change all
your import declarations to hide System.IO.putStrLn and instead import
the version above.
Ben
More information about the Haskell-Cafe
mailing list