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