[posting to the right list... ]
> I guess not. How can you define a non-daemonic forkIO in
> terms of a daemonic one?
> Both suggestions so far involve adding something extra to the
> end of the main
> thread to wait on MVars. And as a matter of fact, neither of
> these solutions
> address the problem of an exception in the main thread
> itself. The only way I can
> see of implementing non-daemonic fork would be to insist that
> the user always write
> main functions with a containing try-finally clause (or
> whatever it's called) which
> does the business of waiting for any unfinished non-daemonic threads.
This is what I'd do. You do need the top-level enclosing exception handler,
but its not at all painful and any program that pretends to be robust will
need one anyway:
(this code is completely untested, BTW)
> import Exception
>
> children :: MVar [MVar ()]
> children = unsafePerformIO (newMVar [])
>
> waitForChildren :: IO ()
> waitForChildren = do
> (mvar:mvars) <- takeMVar children
> putMVar children mvars
> takeMVar mvar
> waitForChildren
>
> forkNonDaemonic :: IO () -> IO ()
> forkNonDaemonic io = do
> mvar <- newEmptyMVar
> forkIO (p `finally` putMVar mvar ())
> childs <- takeMVar children
> putMVar children (mvar:childs)
>
> later = flip finally
>
> main =
> later waitForChildren $
> ...
The trick of having a top-level global mutable variable or MVar is turning
up in a disturbingly large proportion of the code I tend to write these days
:)
Cheers,
Simon