
Isaac Dupree wrote:
It should really be:
block x = do IO blockAsyncExceptions# ret <- x IO unblockAsyncExceptions# return ret
in which case we could then supply implementations for other monads as well.
blockAsyncExceptions# has some tricks to restore tail-recursion in some cases (see the paper). But apart from losing that optimisation, I can't think of any reasons why the above couldn't work - one thing you have to worry about is what happens when x raises an exeption, but I think that is handled by the way we save and restore the blocked state in catch.
what about if the monad is a transformed one with its own error handling methods (e.g. ErrorT IO) and so (IO blockAsyncExceptions#) is run but (IO unblockAsyncExceptions#) is not? Is that a problem?
Yes, in that case you'd need an exception handler in the above code to ensure that unblockAsyncExceptions# was called. Cheers, Simon