<div>Hi Andrew,</div>
<div> </div>
<div>What is needed is the PAR construct: I do not believe any combination of channels can do the same exactly. If C starts after (A|B) finish, etc, then the occam pseudocode (which I hope is self-explanatory) is:</div>
<div> </div>
<div>SEQ</div>
<div> PAR</div>
<div> A</div>
<div> B</div>
<div> --END PAR</div>
<div> C</div>
<div> PAR</div>
<div> D</div>
<div> E</div>
<div> --END PAR</div>
<div> F</div>
<div> </div>
<div>If you want to start them all at the same time it would require some channels to make them end in order:</div>
<div> </div>
<div>PAR</div>
<div> SEQ</div>
<div> PAR</div>
<div> SEQ</div>
<div> PAR</div>
<div> A</div>
<div> B</div>
<div> --END PAR<br> communicate to C</div>
<div> C (communicate from AB)</div>
<div> --END PAR</div>
<div> communicate to D</div>
<div> communicate to E</div>
<div> SEQ</div>
<div> PAR</div>
<div> D (communicate from ABC)</div>
<div> E (communicate from ABC)</div>
<div> --END PAR</div>
<div> communicate to F</div>
<div> F (communicate from DE)</div>
<div>--END PAR</div>
<div> </div>
<div>A PAR requires the parent store two words (its --END PAR resumption instruction address and n-1 where n is the number of children) and start (i.e. schedule) n-1 child tasklets (and branch to the n-th). Each child must terminate with an 'endp' which checks the second word. If it is >0 it decrements it and abandons its instruction stream. If it is 0 it branches to the parent's resumption address.</div>
<div> </div>
<div>Larry<br> </div>
<div><span class="gmail_quote">On 10/22/08, <b class="gmail_sendername">Andrew Francis</b> <<a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a>> wrote:</span>
<blockquote class="gmail_quote" style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">Larry:<br><br>>Do you mean C starts after (A|B) finish, or they all start together, or >..?<br><br>Why did I write that in 2005?<br>
<br>Yes C should start after A AND B finish. However the way the code is written, tasklets actually start before they block on channels.<br><br>The point of that example was it was *very* easy to create a deadlock scenario with a relatively simple precedent graph implemented with just<br>
channels.<br><br>Cheers,<br>Andrew<br><br><br><br><br><br><br>--- On Tue, 10/21/08, Larry Dickson <<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>> wrote:<br><br>> From: Larry Dickson <<a href="mailto:ldickson@cuttedge.com">ldickson@cuttedge.com</a>><br>
> Subject: Re: [Stackless] Stackless based replacement<br>> To: <a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a><br>> Cc: <a href="mailto:stackless@stackless.com">stackless@stackless.com</a><br>
> Date: Tuesday, October 21, 2008, 9:46 AM<br>> Hi Andrew,<br>><br>> I read your 2005 note, and I do not understand<br>><br>> >I expect the following execution trace<br>> ><br>> >(A | B) C (D | E) F<br>
> ><br>> >|* - means processes can execute in parallel.<br>> *><br>> >It is okay to see B finish before A. However it is<br>> >wrong to see C finish before B and A finish.<br>><br>> Do you mean C starts after (A|B) finish, or they all start<br>
> together, or ..?<br>><br>> Larry<br>><br>> On 10/21/08, Andrew Francis <<a href="mailto:andrewfr_ice@yahoo.com">andrewfr_ice@yahoo.com</a>><br>> wrote:<br>> ><br>> > Hi Larry:<br>> ><br>
> > > We seem to have different ideas of what is<br>> simple. You<br>> > > propose exceptions, waits, signals, barriers,<br>> re-initialization,<br>> > > and presumably global signal values. This in my<br>
> opinion is a whole<br>> > >Italian restaurant of spaghetti, and it sounds<br>> intrinsically global, >which<br>> > is poison to maintainable multiprocessing in my<br>> experience.<br>> ><br>
> > This is what I had in mind. A sketch.<br>> ><br>> > def producer(synchronizer):<br>> > try:<br>> > # do some computation<br>> > synchronizer.signal(result)<br>> > except Signalled, data<br>
> > # oops the consumer has moved on.... maybe<br>> > # I should gracefully terminate.....<br>> ><br>> ><br>> > def consumer(synchronizer):<br>> > output = synchronizer.wait()<br>
> > # okay, let us do some stuff with the output<br>> ><br>> > synchronizer = Synchronizer(numberOfProducers)<br>> > stackless.tasklet(consumer)(synchronizer)<br>> > for .... :<br>> > stackless.tasklet(producer)(synchronizer)<br>
> ><br>> > Most of the effort is in defining the right<br>> behaviour.....<br>> ><br>> > Once again, my experiences are when you naively use<br>> channels, it is easy to<br>> > get in trouble. A construct like receive_first()<br>
> looks difficult to<br>> > implement, in comparison to a synchronizer.<br>> ><br>> > Here is a thread from December 2005 (2005!)<br>> ><br>> ><br>> <a href="http://www.stackless.com/pipermail/stackless/2005-December/000290.html">http://www.stackless.com/pipermail/stackless/2005-December/000290.html</a><br>
> ><br>> > Cheers,<br>> > Andrew<br>> ><br>> ><br>> ><br>> ><br>> ><br>> ><br>> ><br>> ><br>> ><br><br><br><br>__________________________________________________<br>
Do You Yahoo!?<br>Tired of spam? Yahoo! Mail has the best spam protection around<br><a href="http://mail.yahoo.com">http://mail.yahoo.com</a><br></blockquote></div><br>