[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

Reply via email to