RE: NON-daemonic forking

1999-08-24 Thread Simon Marlow

[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



Re: NON-daemonic forking

1999-08-23 Thread George Russell

Michael Weber [EMAIL PROTECTED] wrote
[snip]
 forkChild :: IO () - IO (MVar ())
 forkChild p = do
 mvar - newEmptyMVar
 forkIO (p  putMVar mvar ())
 return mvar
This does not of course synthesise a non-daemonic forkIO from a daemonic one, because
it requires the parent thread to wait for the MVar.  I suppose that a possible 
alternative
to having separate daemonic and non-daemonic forking would be to have an atexit-type
function:
   atThreadExit :: IO () - IO()
which forkChild could use to wait for the mvar.  But I'm not sure I like this, unless
there are other likely uses for atThreadExit.



Re: NON-daemonic forking

1999-08-20 Thread Michael Weber

On Fri, Aug 20, 1999 at 15:34:51 +0200, George Russell wrote:
 Einar Karlson, my predecessor, asked for daemonic forking as for Java.  In
 Java you have ordinary threads and daemonic threads; the process ends when
 only daemonic threads are still running.  The GHC team seem to have gone
 ahead and made all forked thread daemonic!  So can we have ordinary threads
 back please?  Still, daemonic threads are nice, and I wonder whether we
 should really have two fork functions, since I can't right now think of a
 way of synthesising one from the other.

How about this one :-)

\begin{code}
import Concurrent( forkIO, MVar, newEmptyMVar, putMVar, readMVar, yield )

main :: IO ()
main = do
t1 - forkChild (forever $ putChar 'a')
t2 - forkChild (forever $ putChar 'b')
waitForChilds [t1, t2]
  where
forever :: IO a - IO a
forever p = p  yield  forever p
\end{code}

\begin{code}
forkChild :: IO () - IO (MVar ())
forkChild p = do
mvar - newEmptyMVar
forkIO (p  putMVar mvar ())
return mvar

waitForChilds :: [MVar ()] - IO ()
waitForChilds [] = return ()
waitForChilds (p:ps) = readMVar p  waitForChilds ps
\end{code}



Cheers,
Michael
-- 
W*ndoze NT is faster... CRASHING!