Hello,<br>I wonder if it might be possible to use just one primitive which atomically changes the interrupt mask for a thread? Here is an example of what I'm thinking:<br><br><font class="Apple-style-span" face="'courier new', monospace">data MaskingState = Unmasked<br>
| MaskedInterruptible<br> | MaskedNonInterruptible<br><br>-- Atomically changes the interrupt mask for a thread, and returns the old mask.<br>setMask :: MaskingState -> IO MaskingState<br>
setMask = error "primitive?"<br><br>-- Change the mask for the duration of an IO action.<br>-- The action is passed the old mask.<br>scopedSetMask :: MaskingState -> (MaskingState -> IO a) -> IO a<br>
scopedSetMask m io = do m1 <- setMask m<br> a <- io m1<br> setMask m1<br> return a<br><br>-- Change the mask for the duration of an IO action.<br>
scopedSetMask_ :: MaskingState -> IO a -> IO a<br>scopedSetMask_ m io = scopedSetMask m $ \_ -><br> io<br>-- Simon's mask:<br>mask :: ((IO a -> IO a) -> IO b) -> IO b<br>
mask f = scopedSetMask MaskedInterruptible $ \m -><br> f (scopedSetMask_ m)</font><br><br><br><div>-Iavor</div><div><br><br>On Sat, Apr 10, 2010 at 11:42 AM, Iavor Diatchki <<a href="mailto:iavor.diatchki@gmail.com">iavor.diatchki@gmail.com</a>> wrote:<br>
> Hello,<br>> It seems that rank-2 types are sufficient to make the more polymorphic types:<br>><br>> ----------------------------------------------------<br>> {-# LANGUAGE Rank2Types #-}<br>> import Control.Exception<br>
><br>> data Mask = Mask (forall a. IO a -> IO a)<br>><br>> mask :: (Mask -> IO a) -> IO a<br>> mask io = do<br>> b <- blocked<br>> if b<br>> then io (Mask id)<br>> else block $ io (Mask unblock)<br>
><br>> restore :: Mask -> IO a -> IO a<br>> restore (Mask f) a = f a<br>> ----------------------------------------------------------<br>><br>> This is useful in an example like this:<br>><br>> forkThen :: IO () -> IO a -> IO a<br>
> forkThen io k = mask $ \m -><br>> do tid <- forkIO (restore m io)<br>> restore m k `catch` \e -><br>> do when (e == ThreadKilled) (killThread tid)<br>> throwIO e<br>><br>> -Iavor<br>
><br>><br>> On Thu, Apr 8, 2010 at 1:23 AM, Simon Marlow <<a href="mailto:marlowsd@gmail.com">marlowsd@gmail.com</a>> wrote:<br>>> On 07/04/2010 18:54, Isaac Dupree wrote:<br>>>><br>>>> On 04/07/10 11:12, Simon Marlow wrote:<br>
>>>><br>>>>> It's possible to mis-use the API, e.g.<br>>>>><br>>>>> getUnmask = mask return<br>>>><br>>>> ...incidentally,<br>>>> unmask a = mask (\restore -> return restore) >>= (\restore -> restore a)<br>
>><br>>> That doesn't work, as in it can't be used to unmask exceptions when they are<br>>> masked. The 'restore' you get just restores the state to its current, i.e.<br>>> masked, state.<br>
>><br>>>>> mask :: ((IO a -> IO a) -> IO b) -> IO b<br>>>><br>>>> It needs to be :: ((forall a. IO a -> IO a) -> IO b) -> IO b<br>>>> so that you can use 'restore' on two different pieces of IO if you need<br>
>>> to. (alas, this requires not just Rank2Types but RankNTypes. Also, it<br>>>> doesn't cure the loophole. But I think it's still essential.)<br>>><br>>> Sigh, yes I suppose that's true, but I've never encountered a case where I<br>
>> needed to call unmask more than once, let alone at different types, within<br>>> the scope of a mask. Anyone else?<br>>><br>>> Cheers,<br>>> Simon<br>>> _______________________________________________<br>
>> Haskell-Cafe mailing list<br>>> <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>>> <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
>><br>><br><br></div>