This is a neat trick indeed!&nbsp; I&#39;d appreciate an explanation of killing one&#39;s own thread and then continuing (with a restart in this case).&nbsp; How does the post-kill resumption occur?&nbsp; That is, how does control pass to the tail-recursive call after the self-kill?<br>
<br>&nbsp; - Conal<br><br><br><div class="gmail_quote">2008/12/28 Peter Verswyvelen <span dir="ltr">&lt;<a href="mailto:bugfact@gmail.com">bugfact@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I fail to understand this part of the code:<div class="Ih2E3d"><div><br></div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case fromException e of<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Just ThreadKilled -&gt; do<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;myThreadId &gt;&gt;= killThread<br><span style="font-weight: bold;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unblock (race a b)<br>

</span></div><div><br></div></div><div>So the current thread gets killed synchronously, then then the race function is evaluated again? The latter I don&#39;t get.</div><div><div></div><div class="Wj3C7c"><div><br></div>
<div><br></div><div><br><div class="gmail_quote">
On Sun, Dec 28, 2008 at 3:03 AM, Bertram Felgenhauer <span dir="ltr">&lt;<a href="mailto:bertram.felgenhauer@googlemail.com" target="_blank">bertram.felgenhauer@googlemail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">

<div>Sterling Clover wrote:<br>
&gt; On Dec 27, 2008, at 9:02 AM, Bertram Felgenhauer wrote:<br>
</div><div>&gt;&gt; In the above code, there is a small window between catching the<br>
&gt;&gt; ThreadKilled exception and throwing it again though, where other<br>
&gt;&gt; exceptions may creep in. The only way I see of fixing that is to use<br>
&gt;&gt; &#39;block&#39; and &#39;unblock&#39; directly.<br>
&gt;<br>
&gt; That certainly seems to do the trick for the simple example at least. One<br>
&gt; way to reason about it better would be, instead of folding everything into<br>
&gt; the race function, to simply modify ghc&#39;s bracket function to give us the<br>
&gt; behavior we&#39;d prefer (speaking of which, I recall there&#39;s something in the<br>
&gt; works for 6.12 or so to improve rethrowing of asynchronous exceptions?)<br>
&gt;<br>
&gt; brackAsync before after thing =<br>
&gt; &nbsp; block (do<br>
&gt; &nbsp; &nbsp; a &lt;- before<br>
&gt; &nbsp; &nbsp; r &lt;- catch<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(unblock (thing a))<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(\_ -&gt; after a &gt;&gt; myThreadId &gt;&gt;= killThread &gt;&gt;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; brackAsync before after thing )<br>
&gt; &nbsp; &nbsp; after a<br>
&gt; &nbsp; &nbsp; return r<br>
&gt; &nbsp;)<br>
&gt; &nbsp; &nbsp; where threadKilled ThreadKilled = Just ()<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; threadKilled _ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;= Nothing<br>
<br>
</div>This code turns any exception into ThreadKilled further down the stack.<br>
<br>
 &nbsp;(\e -&gt; do<br>
 &nbsp; &nbsp; &nbsp; after a<br>
 &nbsp; &nbsp; &nbsp; myThreadId &gt;&gt;= flip throwTo (e :: SomeException)<br>
 &nbsp; &nbsp; &nbsp; ...<br>
<br>
might do the trick.<br>
<br>
My assumption was that anything but &#39;ThreadKilled&#39; would be a<br>
real error. This isn&#39;t really true, I guess - thanks to throwTo,<br>
any exception could be asynchronous.<br>
<br>
If an exception is thrown, &#39;after a&#39; is run again after the computation<br>
has resumed.<br>
<br>
That&#39;s why I did the cleanup within the &#39;catch&#39;.<br>
<br>
But there&#39;s no reason why you couldn&#39;t do that as well:<br>
<div><br>
 &nbsp;brackAsync before after thing =<br>
 &nbsp; &nbsp;block $ do<br>
 &nbsp; &nbsp; &nbsp;a &lt;- before<br>
</div> &nbsp; &nbsp; &nbsp;catch &nbsp;(unblock (thing a) &gt;&gt;= \r -&gt; after a &gt;&gt; return r) $<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \e -&gt; do<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;after a<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;myThreadId &gt;&gt;= flip throwTo (e :: SomeException)<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;brackAsync before after thing )<br>
<div><br>
&gt; This brackAsync just drops in to the previous code where bracket was and<br>
&gt; appears to perform correctly.<br>
<br>
</div>Right. &#39;race&#39; should also unblock exceptions in the worker threads,<br>
<br>
 &nbsp; &nbsp;withThread u v = brackAsync (forkIO (unblock u)) killThread (const v)<br>
<br>
but that&#39;s an independent change.<br>
<div><br>
&gt; Further, if we place a trace after the<br>
&gt; killThread, we se it gets executed once when the example is read (i.e. a<br>
&gt; resumption) but it does not get executed if the (`seq` v) is removed from<br>
&gt; the example So this gives me some hope that this is actually doing what<br>
&gt; we&#39;d like. I don&#39;t doubt it may have further kinks however.<br>
<br>
</div>At least the GHC RTS has support for the hard part - unwinding the stack<br>
so that computations can be resumed seamlessly.<br>
<br>
I&#39;m not sure which of the approaches I like better - it seems that we<br>
have a choice between turning async exceptions into sync ones or vice<br>
versa, and neither choice is strictly superior to the other.<br>
<br>
Enjoy,<br>
<br>
Bertram<br>
<br>
&#39;race&#39; update:<br>
- Bugfix: Previously, only AsyncException-s would be caught.<br>
 &nbsp;Use &#39;fromException&#39; to select the ThreadKilled exception.<br>
- I tried using a custom &#39;SuspendException&#39; type, but this resulted in<br>
 &nbsp;&#39;test: SuspendException&#39; messages on the console, while ThreadKilled<br>
 &nbsp;is silently ignored... as documented:<br>
 &nbsp; &nbsp; <a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#v%3AforkIO" target="_blank">http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#v%3AforkIO</a><br>


 &nbsp; &nbsp; (<a href="http://tinyurl.com/9t5pxs" target="_blank">http://tinyurl.com/9t5pxs</a>)<br>
- Tweak: Block exceptions while running &#39;cleanup&#39; to avoid killing<br>
 &nbsp;threads twice.<br>
- Trick: takeMVar is a blocking operation, so exceptions can be<br>
 &nbsp;delivered while it&#39;s waiting - there&#39;s no need to use &#39;unblock&#39; for<br>
 &nbsp;this. In other words, &nbsp;unblock (takeMVar v) &nbsp;and &nbsp;takeMVar v &nbsp;are<br>
 &nbsp;essentially equivalent for our purposes.<br>
<div><br>
race :: IO a -&gt; IO a -&gt; IO a<br>
</div>race a b = block $ do<br>
 &nbsp; &nbsp;v &lt;- newEmptyMVar<br>
 &nbsp; &nbsp;let t x = unblock (x &gt;&gt;= putMVar v)<br>
 &nbsp; &nbsp;ta &lt;- forkIO (t a)<br>
 &nbsp; &nbsp;tb &lt;- forkIO (t b)<br>
 &nbsp; &nbsp;let cleanup = killThread ta &gt;&gt; killThread tb<br>
 &nbsp; &nbsp;(do r &lt;- takeMVar v; cleanup; return r) `catch`<br>
 &nbsp; &nbsp; &nbsp; &nbsp;\e -&gt; cleanup &gt;&gt;<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;case fromException e of<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Just ThreadKilled -&gt; do<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;myThreadId &gt;&gt;= killThread<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unblock (race a b)<br>
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_ -&gt; throwIO e<br>
<div><div></div><div>_______________________________________________<br>
Reactive mailing list<br>
<a href="mailto:Reactive@haskell.org" target="_blank">Reactive@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/reactive" target="_blank">http://www.haskell.org/mailman/listinfo/reactive</a><br>
</div></div></blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
Reactive mailing list<br>
<a href="mailto:Reactive@haskell.org">Reactive@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/reactive" target="_blank">http://www.haskell.org/mailman/listinfo/reactive</a><br>
<br></blockquote></div><br>