<html><body><div style="color:#000; background-color:#fff; font-family:times new roman, new york, times, serif;font-size:12pt"><div><span>Hi Richard and Folks:</span></div><div><br></div><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"><div style="font-family: 'times new roman', 'new york', times, serif; font-size: 12pt;"><div class="y_msg_container">Message: 4<br>Date: Tue, 3 Sep 2013 11:05:46 +1200<br>From: Richard Tew <<a ymailto="mailto:richard.m.tew@gmail.com" href="mailto:richard.m.tew@gmail.com">richard.m.tew@gmail.com</a>><br>To: The Stackless Python Mailing List <<a ymailto="mailto:stackless@stackless.com" href="mailto:stackless@stackless.com">stackless@stackless.com</a>><br>Subject: Re: [Stackless] stacklesslib.async<br>Message-ID:<br>    <CAN=X-TEZZ8P2vOgU2FDEiQ7WcWodHVY5-bkiJrjn0bBDzbzq+<a ymailto="mailto:g@mail.gmail.com"
 href="mailto:g@mail.gmail.com">g@mail.gmail.com</a>><br>Content-Type: text/plain; charset=ISO-8859-1<br><br>I've created a different title but I do want to look at Kristjan's module and keep those comments independent.</div><div class="y_msg_container"><br>>And having written all this, the elephant in the room is that I<br>>believe CSP, which Andrew Francis has long been advocating, is closer<br>>to what I think we need.  <br><br>:-)</div><div class="y_msg_container"><br>It is my belief that synchronous first order channels (that is the channels themselves can be sent in messages) with buffering provides a simple yet powerful concurrency model. I strongly believe that we can hide asynchrony from the application programmer.<br><br></div><div class="y_msg_container"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>Then again, why return indexes.  That just means
 you have to waste</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>time holding onto the original list, if you do not have a permanent</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>one.</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"></div><div class="y_msg_container"><br></div><div class="y_msg_container">Looking at Go's API version of Select in the reflect package, it also returns an index. I think returning an index is a more flexible way of identifying a completed channel from a big list. From my
 experience with my own implementations, you tend to want to create the list once before entering a loop. Hence you are holding on to it, even manipulating it along the way. Or for that matter, you are taking the result and doing some set inclusion operation. So again having the original list helps.</div><div class="y_msg_container"><br></div><div class="y_msg_container"><div>>However, I've long had problems with using it ad hoc, as I think it is not that user friendly and is >more theoretically balanced than functionally balanced.<br></div><div><br></div><div>I took my initial cues for an API from Polyphonic C# and the Concurrent Visual Basic join library. This was a mistake. Also the initial thrust of my work was to figure out what the internal model would look like, so API design was an afterthought. </div><div><br></div><div>Until now, I have felt that folks on the Stackless mailing list have thrown the baby out with the
 bathwater when I introduced select and join. It doesn't help that I was defensive at the time, haven't released a copy of the code (it is messy with few tests) or for that matter given a good presentation. </div><div><br></div><div><span style="font-size: 12pt;">I have been redesigning the API and I am about to write a new module (I'll call it joinStackless.py so I don't create confusion with stackless.py). </span></div><div><span style="font-size: 12pt;"><br></span></div><div><span style="font-size: 12pt;">I decided that to keep the API simple by not introducing new objects (i.e., chanops, joinPatterns, methods on channels). Consequently you have to deal with lists and tuples and some constants. </span><span style="font-size: 12pt;">Then again, Python has comprehensions so this is a more Pythonic approach. Also from Pycon Canada 2012, I found I could simplify the user's experience by of the API by implementing a crude parametric
 polymorphism and type check arguments.</span></div><div><br></div><div><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>But I think that this should not just handle tasklet completion, it</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>should also handle tasklets producing results via channels.  In that</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>case, it is useful to poll whether any tasklets have results, rather</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica,
 Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>than waitX with a minimum timeout.</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>I think that this should be in, but there surely can be a more natural</span><br style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;"><span style="color: rgb(69, 69, 69); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px;">>fit.  And this might mean a requirement for lower level support.</span><br></div><div><br></div><div>To
 me, tasklets signalling completion through a channel is a perfectly fine way to do things. I think with C# style Tasks, you have to look at the result property (which may block, but I have to check this). As for the low level support. That is a select method with some join pattern support.</div><div><br></div><div>Right now I am toying with a new stackless.select (or stackless.alt, the name 'select' seems to confuse folks)</div><div><br></div><div>def select(operations, default = False)</div><div>      """</div><div>      block on a set of operations until an operation is COMPLETED.</div><div>      in case of a tie, an operation is chosen at random</div><div>      if default is True, select returns if no operation has completed.</div><div><br></div><div>      operations List:  list of operations in the form the tuple (channel, channel operation, value)</div><div> 
                               </div><div>                                or</div><div>                                 </div><div>                                ([], count)</div><div>                                where [] is a list of channels. Only RECV is allowed here</div><div>                                count the number of operations to wait on.</div><div><br></div><div>                           
     for bevity</div><div>                                [] </div><div>                                if all operations must complete, the tuple can be omitted</div><div><br></div><div>      Return: tuple (index, value)  </div><div>      value is (None, None) if default invoked</div><div>      value is (index, None) if a SEND operation</div><div>      value is (index, [(index, value)]) if a join pattern has completed</div><div><br></div><div>To me, waitAny would look like</div><div><br></div><div>operations = [(chan1, RECV),  (chan2, RECV), (cha3, SEND, 10), (ch_timeout, RECV)]</div><div>(index, value) = stackless.select(operations)</div><div><br></div><div>as for waitAll</div><div><br></div><div>using the Santa
 Claus problem as an example:</div><div><br></div><div><div>elves = [ a list of elf channels ]</div><div><span style="font-size: 12pt;">reindeer = [ a list of reindeer channels ]</span></div><div><span style="font-size: 12pt;"><br></span></div><div><span style="font-size: 12pt;">(index, value) = stackless.select([(elves, 3), reindeer])</span></div></div><div><br></div><div>so if any 3 of the 10 elves have completed, say elf 0, elf 5 and elf 9</div><div><br></div><div>(0, [(0, value), (5, value), (9, value)])</div><div><br></div><div>if all nine reindeer completed,</div><div><br></div><div>(1,[0, value),(1, value) .... (8, value)])</div><div><br></div><div>Hopefully I'll start working on this during the weekend and get something out in a week that folks here can say Yeah or Nay or why don't you do it this way.</div><div><br></div><div>Cheers,</div><div>Andrew</div></div> </div> </div>  </div></body></html>