
On April 9, 2010 06:05:36 Simon Marlow wrote:
On 08/04/2010 21:20, Tyson Whitehead wrote:
Of course you've then got the problem of umask having to produce a valid value even when IO a was aborted, so you would have to go with something like
unmask :: a -> IO a -> IO a
where the first a gets returned if the IO a computation gets aborted by an exception. The original problem code would then go from
I haven't seen anyone else asking for this kind of design, and it's quite different to both what we have now and the new proposal. What advantages would this have, do you think?
My understanding was that, for a given block of code, it would be nice to be able to ensure asynchronous exceptions are always unblocked. This is something that the nested design doesn't give you because it is going to depend on the context in which a block of code is ran. My understanding about the problem with the currently implemented design is that asynchronous exception will still abort the normal evaluation flow when ever a called routine unblocked exceptions as this then allows them to be turned into standard synchronous exceptions. My suggestion was then aimed at seeing if their was a way to ensure the standard evaluation flow resumed. In retrospect, I'm not sure it was a good suggestion. Although it ensures modifyMVar leaves things in a consistent state, it is likely less than desirable for the function calling modifyMVar to have have control returned to it with no idea whether the modification was successful or not until it unblocks exceptions sometime later. Looking back at the original problem, I was wondering if the problem was simply that the understanding the block gives you an "atomic transaction" is simply not true. Thus the outer block of code block $ do ... modifyMVar_ m f ... should be using proper exception wrapping around any resources it acquires to ensure that they always get cleaned up. Of course this then brings you in full circle as you have the problem that an "asynchronous exception wormhole" could also occur in your cleanup code. This leads me to conclude that nesting really is the correct solution, and the answer to the problem of exception being potentially blocked for too long is that properly written code should strive to limit the amount of time they are blocked (i.e., really just for the acquisition and releasing of resources). A different, but related issue then might be what are alternate form of the primitives block and unblock to help ensure they aren't abused? Something like bracket where the acquisition and release run with exception blocked and the body with them re-enabled? Anyways, enough of my rambling, I'll let you guys get back to figuring out how to ensure that nesting is not abused. Cheers! -Tyson