(I&#39;m broadening the discussion to include haskell-cafe.)<br><br>Andy -- What do you mean by &quot;handling all&nbsp;thread forking locally&quot;?<br><br>&nbsp; - Conal<br><br><div class="gmail_quote">On Thu, Dec 18, 2008 at 1:57 PM, Andy Gill <span dir="ltr">&lt;<a href="mailto:andygill@ku.edu">andygill@ku.edu</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 style="">Conal, et. al,<div><br></div><div>I was looking for exactly this about 6~9 months ago. I got the suggestion to pose it as a&nbsp;challenge</div>
<div>to the community by Duncan Coutts. What you need is thread groups, &nbsp;where for a ThreadId, you can send a signal</div><div>to all its children, even missing generations if needed.&nbsp;</div><div><br></div><div>I know of no way to fix this at the Haskell level without handling all&nbsp;thread forking locally.&nbsp;</div>
<div><br></div><div>Perhaps a ICFP paper about the pending implementation :-) but I&#39;m not sure about the research content here.</div><div><br></div><div>Again, there is something deep about values with lifetimes.&nbsp;</div>
<div><br></div><div>Andy Gill</div><div><br></div><div><br><div><div><div><div></div><div class="Wj3C7c"><div>On Dec 18, 2008, at 3:43 PM, Conal Elliott wrote:</div><br></div></div><blockquote type="cite"><div><div></div>
<div class="Wj3C7c">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><br>&nbsp;&nbsp; - Conal<br><br><br></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></blockquote>
</div><br></div></div></div></blockquote></div><br>