
Hi, Bertram Felgenhauer wrote: [snip]
race :: IO a -> IO a -> IO a
Two quick notes on that function:
race a b = block $ do v <- newEmptyMVar let t x = x >>= putMVar v
Should be let t x = unblock (x >>= putMVar v) Otherwise the computation 'x' not be interruptible unless it explicitely uses 'unblock' or a blocking operation like reading an MVar.
ta <- forkIO (t a) tb <- forkIO (t b) let cleanup = killThread ta >> killThread tb unblock (do r <- takeMVar v; cleanup; return r) `catch` \e -> case e of ThreadKilled -> do cleanup myThreadId >>= killThread unblock (race a b)
On the other hand, this 'unblock' should have no effect: If we ever return here, it'll be in a different thread, or after another exception handler has enabled exceptions for the current thread.
e -> throwIO e
Oops. This should call cleanup as well. (I guess it should be done before the 'case' expression) e -> cleanup >> throwIO e Bertram