On 09/04/2010 09:40, Bertram Felgenhauer wrote:
Simon Marlow wrote:
but they are needlessly complicated, in my opinion.  This offers the
same functionality:

mask :: ((IO a ->  IO a) ->  IO b) ->  IO b
mask io = do
   b<- blocked
   if b
      then io id
      else block $ io unblock

How does forkIO fit into the picture? That's one point where reasonable
code may want to unblock all exceptions unconditionally - for example to
allow the thread to be killed later.

Sure, and it works exactly as before in that the new thread inherits the masking state of its parent thread. To unmask exceptions in the child thread you need to use the restore operator passed to the argument of mask.

This does mean that if you fork a thread inside mask and don't pass it the restore operation, then it has no way to ever unmask exceptions. At worst, this means you have to pass a restore value around where you didn't previously.

     timeout t io = block $ do
         result<- newEmptyMVar
         tid<- forkIO $ unblock (io>>= putMVar result)
         threadDelay t `onException` killThread tid
         killThread tid
         tryTakeMVar result

This would be written

>      timeout t io = mask $ \restore -> do
>          result<- newEmptyMVar
>          tid<- forkIO $ restore (io>>= putMVar result)
>          threadDelay t `onException` killThread tid
>          killThread tid
>          tryTakeMVar result

though the version of timeout in System.Timeout is better for various reasons.

Cheers,
        Simon
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to