I thought that killing a thread was basically done by throwing a ThreadKilled exception using throwTo. Can&#39;t these exception be caught?&nbsp;<div><div><br></div><div>In C#/F# I usually use a similar technique: catch the exception that kills the thread, and perform cleanup. I have no experience with Haskell in that regard so most likely I&#39;m missing something here...</div>
<div><br><div class="gmail_quote">2008/12/18 Conal Elliott <span dir="ltr">&lt;<a href="mailto:conal@conal.net">conal@conal.net</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
I realized in the shower this morning that there&#39;s a serious flaw in my unamb implementation as described in <a href="http://conal.net/blog/posts/functional-concurrency-with-unambiguous-choice" target="_blank">http://conal.net/blog/posts/functional-concurrency-with-unambiguous-choice</a>.&nbsp; I&#39;m looking for ideas for fixing the flaw.&nbsp; Here&#39;s the code for racing computations:<br>

<br><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp; race :: IO a -&gt; IO a -&gt; IO a</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp; a `race` b = do v&nbsp; &lt;- newEmptyMVar</span><br style="font-family:courier new,monospace">

<span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ta &lt;- forkPut a v</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tb &lt;- forkPut b v</span><br style="font-family:courier new,monospace">

<span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x&nbsp; &lt;- takeMVar&nbsp; v</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; killThread ta</span><br style="font-family:courier new,monospace">

<span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; killThread tb</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return x</span><br style="font-family:courier new,monospace">

<br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp; forkPut :: IO a -&gt; MVar a -&gt; IO ThreadId</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp; forkPut act v = forkIO ((act &gt;&gt;= putMVar v) `catch` uhandler `catch` bhandler)</span><br style="font-family:courier new,monospace">

<span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp; where</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uhandler (ErrorCall &quot;Prelude.undefined&quot;) = return ()</span><br style="font-family:courier new,monospace">

<span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uhandler err&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = throw err</span><br style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bhandler BlockedOnDeadMVar&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = return ()</span><br>

<br>The problem is that each of the threads ta and tb may have spawned other threads, directly or indirectly.&nbsp; When I kill them, they don&#39;t get a chance to kill their sub-threads.<br><br>Perhaps I want some form of garbage collection of threads, perhaps akin to Henry Baker&#39;s paper &quot;The Incremental Garbage Collection of Processes&quot;.&nbsp; As with memory GC, dropping one consumer would sometimes result is cascading de-allocations.&nbsp; That cascade is missing from my implementation.<br>

<br>Or maybe there&#39;s a simple and dependable manual solution, enhancing the method above.<br><br>Any ideas?<br><font color="#888888"><br>&nbsp;&nbsp; - Conal<br><br><br>
</font><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></div></div>