<div dir="ltr"><br><br><div class="gmail_quote">On Wed, Oct 8, 2008 at 3:10 PM, roger peppe <span dir="ltr">&lt;<a href="mailto:rogpeppe@gmail.com">rogpeppe@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
I was wondering if it was possible to implement synchronous channels<br>
within STM. In particular, I&#39;d like to have CSP-like send and recv primitives<br>
on a channel that each block until the other side arrives to complete<br>
the transaction.</blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
<br>
I think I&#39;ve convinced myself that it&#39;s not possible, but<br>
anyone care to differ?</blockquote><div><br></div><div>Hi Rog!! &nbsp;(Plan 9/Inferno Rog?)</div><div><br></div><div><a href="http://haskell.org/ghc/docs/latest/html/libraries/stm/Control-Concurrent-STM-TChan.html">http://haskell.org/ghc/docs/latest/html/libraries/stm/Control-Concurrent-STM-TChan.html</a> &nbsp;&lt;-- isn&#39;t that it?<br>
</div><div><br></div><div>see writeTChan and readTChan. &nbsp;I assume readTChan is synchronous :-). &nbsp;writeTChan may be asynchronous for all I can tell (haven&#39;t looked deeply). &nbsp;</div><div><br></div><div>But I did write a concurrent prime sieve with it:</div>
<div><br></div><div><div>module Main where</div><div><br></div><div>{--</div><div>Haskell Concurrent and sometimes parallel prime sieve of eratosthenes</div><div>&lt;leimy2kNOSP@M@<a href="http://mac.com">mac.com</a>&gt;</div>
<div>David Leimbach</div><div>May 19, 2008</div><div><br></div><div>Communicates with typed data channels for sieving using the STM monad (Software Transactional Memory) to&nbsp;</div><div>share data between sparks. &nbsp;Sparks are created by forkIO, which can be scheduled to real OS threads.</div>
<div><br></div><div>The algorithm is sloppily contained in sieve :: TChan Int -&gt; TChan Int -&gt; IO ()&nbsp;</div><div>which receives a number in the range of [2 .. 10000]. &nbsp;If this is the first number it has received, that</div>
<div>will forever be that spark&#39;s number to test for divisibility of subsequent numbers. &nbsp;After this assignment</div><div>it writes this value to the reader spark which prints it and waits for the next number to fall out of the</div>
<div>sieve. (which is why we start with 2)</div><div><br></div><div>This first sieve running spark will forkIO 1 more sieve spark that will be sent as it&#39;s first number, the</div><div>first number not evenly divisible by the value of the current sieve spark. &nbsp;</div>
<div><br></div><div>This process continues until the syncVal is received, which terminates the program and shuts down the reader</div><div>as well as the main loop.</div><div>--}</div><div><br></div><div>import Control.Monad.STM</div>
<div>import Control.Monad</div><div>import Control.Concurrent</div><div>import Control.Concurrent.STM.TChan</div><div><br></div><div>import System(getArgs)</div><div><br></div><div>syncVal :: Int</div><div>syncVal = -1</div>
<div><br></div><div>sieve :: TChan Int -&gt; TChan Int -&gt; IO ()</div><div>sieve inChan outChan &nbsp;= &nbsp;do</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> value &lt;- atomically $ readTChan inChan</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> atomically $ writeTChan outChan value</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> newchan &lt;- atomically $ newTChan</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> forkIO $ sieve newchan outChan</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> forever value newchan</div><div>&nbsp;&nbsp; &nbsp;where forever value newchan = do</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp;subsequent &lt;- atomically $ readTChan inChan</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp;if subsequent `mod` value /= 0&nbsp;</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp; &nbsp; then</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp; &nbsp; &nbsp; do</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp; &nbsp; &nbsp; atomically $ writeTChan newchan subsequent</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp; &nbsp; &nbsp; forever value newchan</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span> &nbsp; &nbsp; else if subsequent == syncVal</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span> &nbsp; &nbsp; then</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span> &nbsp; &nbsp; &nbsp; do&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span> &nbsp; &nbsp; &nbsp; atomically $ writeTChan outChan syncVal</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span> &nbsp; &nbsp; &nbsp; return ()</div>
<div><span class="Apple-tab-span" style="white-space:pre">                                        </span> &nbsp; &nbsp; else</div><div><span class="Apple-tab-span" style="white-space:pre">                                        </span> &nbsp; &nbsp; &nbsp; forever value newchan</div><div><br></div><div>reader :: TChan Int -&gt; TChan Char -&gt; IO ()</div>
<div>reader chan syncChan = do&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>x &lt;- atomically $ readTChan chan&nbsp;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>if x /= syncVal</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; then</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; &nbsp; &nbsp; do&nbsp;</div><div>--<span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; &nbsp; &nbsp; putStrLn $ show x</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; &nbsp; &nbsp; reader chan syncChan</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; else</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; &nbsp; &nbsp; do</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; &nbsp; &nbsp; atomically $ writeTChan syncChan &#39;Q&#39;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span> &nbsp; &nbsp; &nbsp; return ()</div><div><br>
</div><div>main :: IO ()</div><div>main = do</div><div>&nbsp;&nbsp; &nbsp; &nbsp; wChannel &lt;- atomically $ newTChan</div><div>&nbsp;&nbsp; &nbsp; &nbsp; rChannel &lt;- atomically $ newTChan</div><div>&nbsp;&nbsp; &nbsp; &nbsp; sChannel &lt;- atomically $ newTChan</div><div>&nbsp;&nbsp; &nbsp; &nbsp; forkIO $ reader rChannel sChannel</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; forkIO $ sieve wChannel rChannel</div><div>&nbsp;&nbsp; &nbsp; &nbsp; x &lt;- getArgs</div><div>&nbsp;&nbsp; &nbsp; &nbsp; putStrLn (&quot;Searching for primes up to &quot; ++ (head x))</div><div>&nbsp;&nbsp; &nbsp; &nbsp; forM_ [2 .. ((read (head x)) ::Int)] $ \i -&gt; atomically $ writeTChan wChannel i</div>
<div>&nbsp;&nbsp; &nbsp; &nbsp; atomically $ writeTChan wChannel syncVal</div><div>&nbsp;&nbsp; &nbsp; &nbsp; atomically $ readTChan sChannel</div><div>&nbsp;&nbsp; &nbsp; &nbsp; return ()</div><div>&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;</div><div><br></div></div><div><br></div><div><br></div><div>&nbsp;</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
<br>
 &nbsp;cheers,<br>
 &nbsp; &nbsp;rog.<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" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</blockquote></div><br></div>