<div><br>&gt; I solved my problem in 2005. I wrote a synchronizer construct similar to what</div>
<div>&gt; I previously posted. I believe the uthread module had counting semaphores.</div>
<div>&gt; I make the assumption that tasklets terminate soon after they join. This keeps</div>
<div>&gt; the code simple. Under the hood, only one, not number of children + 1</div>
<div>&gt; channels, are used.<br>&gt;<br>&gt; That said, I think we are going around in circles....<br>&nbsp;</div>
<div>I agree, we seem to be talking past each other. For the realistic&nbsp;interpretation (start C after (A|B) finish), PAR&nbsp;uses&nbsp;no channels, no counting semaphores, and no tasklet survival after a join, thus no races. That certainly seems to qualify as simpler; but it needs the ability to spawn child tasklets that do the equivalent of an endp when they terminate. If this exists in Stackless, then the problem is trivial.</div>

<div>&nbsp;</div>
<div>Larry</div>
<div>&nbsp;</div>
<div><span class="gmail_quote">On 10/22/08, <b class="gmail_sendername">Andrew Francis</b> &lt;<a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a>&gt; wrote:</span>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">Hello Larry:<br><br><br>&gt;What is needed is the PAR construct: I do not believe any combination of<br>&gt;channels can do the same exactly. If C starts after (A|B) finish, etc, &gt;then the occam pseudocode (which I hope is self-explanatory) is:<br>
<br>I solved my problem in 2005. I wrote a synchronizer construct similar to what I previously posted. I believe the uthread module had counting semaphores. I make the assumption that tasklets terminate soon after they join. This keeps the code simple. Under the hood, only one, not number of children + 1&nbsp;&nbsp;channels, are used.<br>
<br>That said, I think we are going around in circles....<br><br>I think Jeff Senn is right in that most Stackless users have a similar philosophical approach - that is if you want a new construct - roll your own in a module, rather than add to Stackless. Again, I believe channels are a very very powerful building block. However channels by themselves can be a very blunt instrument for complex tasks.<br>
<br>In regard to networking, I think the anarchical approach has worked. Some Stackless users like stacklessSocket module with LibEvent. I like using Twisted (and Twisted could be used with LibEvent).<br><br>Since I believe this thread originally began with asynchronous I/O, regardless of technique, there are basic gotchas. Perhaps if we could all agree on the basic gotchas, this knowledge could be modelled with PyPy and if it works, be placed in Stackless Python.<br>
<br>Cheers,<br>Andrew<br><br><br><br><br>--- On Wed, 10/22/08, Larry Dickson &lt;<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>&gt; wrote:<br><br>&gt; From: Larry Dickson &lt;<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>&gt;<br>
&gt; Subject: Re: [Stackless] Stackless based replacement<br>&gt; To: &quot;Andrew Francis&quot; &lt;<a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a>&gt;<br>&gt; Cc: <a href="mailto:stackless@stackless.com">stackless@stackless.com</a><br>
&gt; Date: Wednesday, October 22, 2008, 7:21 AM<br>&gt; Hi Andrew,<br>&gt;<br>&gt; What is needed is the PAR construct: I do not believe any<br>&gt; combination of<br>&gt; channels can do the same exactly. If C starts after (A|B)<br>
&gt; finish, etc, then<br>&gt; the occam pseudocode (which I hope is self-explanatory) is:<br>&gt;<br>&gt; SEQ<br>&gt;&nbsp;&nbsp; PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; A<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; B<br>&gt;&nbsp;&nbsp; --END PAR<br>&gt;&nbsp;&nbsp; C<br>&gt;&nbsp;&nbsp; PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; D<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; E<br>
&gt;&nbsp;&nbsp; --END PAR<br>&gt;&nbsp;&nbsp; F<br>&gt;<br>&gt; If you want to start them all at the same time it would<br>&gt; require some<br>&gt; channels to make them end in order:<br>&gt;<br>&gt; PAR<br>&gt;&nbsp;&nbsp; SEQ<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SEQ<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --END PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; communicate to C<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C (communicate from AB)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; --END PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; communicate to D<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; communicate to E<br>
&gt;&nbsp;&nbsp; SEQ<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; D (communicate from ABC)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; E (communicate from ABC)<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; --END PAR<br>&gt;&nbsp;&nbsp;&nbsp;&nbsp; communicate to F<br>&gt;&nbsp;&nbsp; F (communicate from DE)<br>&gt; --END PAR<br>&gt;<br>&gt; A PAR requires the parent store two words (its --END PAR<br>
&gt; resumption<br>&gt; instruction address and n-1 where n is the number of<br>&gt; children) and start<br>&gt; (i.e. schedule) n-1 child tasklets (and branch to the<br>&gt; n-th). Each child must<br>&gt; terminate with an &#39;endp&#39; which checks the second<br>
&gt; word. If it is &gt;0 it<br>&gt; decrements it and abandons its instruction stream. If it is<br>&gt; 0 it branches to<br>&gt; the parent&#39;s resumption address.<br>&gt;<br>&gt; Larry<br>&gt;<br>&gt; On 10/22/08, Andrew Francis &lt;<a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a>&gt;<br>
&gt; wrote:<br>&gt; &gt;<br>&gt; &gt; Larry:<br>&gt; &gt;<br>&gt; &gt; &gt;Do you mean C starts after (A|B) finish, or they<br>&gt; all start together, or<br>&gt; &gt; &gt;..?<br>&gt; &gt;<br>&gt; &gt; Why did I write that in 2005?<br>
&gt; &gt;<br>&gt; &gt; Yes C should start after A AND B&nbsp;&nbsp;finish. However the<br>&gt; way the code is<br>&gt; &gt; written,&nbsp;&nbsp;tasklets actually start before they block on<br>&gt;&nbsp;&nbsp;channels.<br>&gt; &gt;<br>&gt; &gt; The point of that example was it was *very* easy to<br>
&gt; create a deadlock<br>&gt; &gt; scenario with a relatively simple precedent graph<br>&gt; implemented with just<br>&gt; &gt; channels.<br>&gt; &gt;<br>&gt; &gt; Cheers,<br>&gt; &gt; Andrew<br>&gt; &gt;<br>&gt; &gt;<br>
&gt; &gt;<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt; --- On Tue, 10/21/08, Larry Dickson<br>&gt; &lt;<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>&gt; wrote:<br>&gt; &gt;<br>&gt; &gt; &gt; From: Larry Dickson &lt;<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>&gt;<br>
&gt; &gt; &gt; Subject: Re: [Stackless] Stackless based<br>&gt; replacement<br>&gt; &gt; &gt; To: <a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a><br>&gt; &gt; &gt; Cc: <a href="mailto:stackless@stackless.com">stackless@stackless.com</a><br>
&gt; &gt; &gt; Date: Tuesday, October 21, 2008, 9:46 AM<br>&gt; &gt; &gt; Hi Andrew,<br>&gt; &gt; &gt;<br>&gt; &gt; &gt; I read your 2005 note, and I do not understand<br>&gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;I expect the following execution trace<br>
&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;(A | B) C (D | E) F<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;|* - means processes can execute in parallel.<br>&gt; &gt; &gt; *&gt;<br>&gt; &gt; &gt; &gt;It is okay to see B finish before A. However<br>
&gt; it is<br>&gt; &gt; &gt; &gt;wrong to see C finish before B and A finish.<br>&gt; &gt; &gt;<br>&gt; &gt; &gt; Do you mean C starts after (A|B) finish, or they<br>&gt; all start<br>&gt; &gt; &gt; together, or ..?<br>&gt; &gt; &gt;<br>
&gt; &gt; &gt; Larry<br>&gt; &gt; &gt;<br>&gt; &gt; &gt; On 10/21/08, Andrew Francis<br>&gt; &lt;<a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a>&gt;<br>&gt; &gt; &gt; wrote:<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; Hi Larry:<br>
&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; &gt; We seem to have different ideas of what<br>&gt; is<br>&gt; &gt; &gt; simple. You<br>&gt; &gt; &gt; &gt; &gt; propose exceptions, waits, signals,<br>&gt; barriers,<br>&gt; &gt; &gt; re-initialization,<br>
&gt; &gt; &gt; &gt; &gt; and presumably global signal values.<br>&gt; This in my<br>&gt; &gt; &gt; opinion is a whole<br>&gt; &gt; &gt; &gt; &gt;Italian restaurant of spaghetti, and it<br>&gt; sounds<br>&gt; &gt; &gt; intrinsically global, &gt;which<br>
&gt; &gt; &gt; &gt; is poison to maintainable multiprocessing in<br>&gt; my<br>&gt; &gt; &gt; experience.<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; This is what I had in mind. A sketch.<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; def producer(synchronizer):<br>
&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# do some computation<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;synchronizer.signal(result)<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;except Signalled, data<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# oops the consumer has moved on....<br>
&gt; maybe<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# I should gracefully terminate.....<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; def consumer(synchronizer):<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;output = synchronizer.wait()<br>
&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;# okay, let us do some stuff with the<br>&gt; output<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; synchronizer =<br>&gt; Synchronizer(numberOfProducers)<br>&gt; &gt; &gt; &gt; stackless.tasklet(consumer)(synchronizer)<br>
&gt; &gt; &gt; &gt; for .... :<br>&gt; &gt; &gt; &gt;&nbsp;&nbsp;&nbsp;&nbsp;stackless.tasklet(producer)(synchronizer)<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; Most of the effort is in defining the right<br>&gt; &gt; &gt; behaviour.....<br>
&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; Once again, my experiences are when you<br>&gt; naively use<br>&gt; &gt; &gt; channels, it is easy to<br>&gt; &gt; &gt; &gt; get in trouble.&nbsp;&nbsp;A construct like<br>&gt; receive_first()<br>
&gt; &gt; &gt; looks difficult to<br>&gt; &gt; &gt; &gt; implement, in comparison to a synchronizer.<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; Here is a thread from December 2005 (2005!)<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>&gt; <a href="http://www.stackless.com/pipermail/stackless/2005-December/000290.html">http://www.stackless.com/pipermail/stackless/2005-December/000290.html</a><br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt; Cheers,<br>
&gt; &gt; &gt; &gt; Andrew<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>&gt; &gt; &gt; &gt;<br>
&gt; &gt;<br>&gt; &gt;<br>&gt; &gt;<br>&gt; &gt; __________________________________________________<br>&gt; &gt; Do You Yahoo!?<br>&gt; &gt; Tired of spam?&nbsp;&nbsp;Yahoo! Mail has the best spam<br>&gt; protection around<br>&gt; &gt; <a href="http://mail.yahoo.com">http://mail.yahoo.com</a><br>
&gt; &gt;<br><br><br><br></blockquote></div><br>