Ann: Stackless Limbo Dancing Works Fine!

Christian Tismer tismer at tismer.com
Mon May 20 03:51:38 EDT 2002


Fernando Pereira wrote:
[about PAR etc.]

[me, comparing it to my stuff]

> I've not looked at this stuff since the mid 80s, but my recollection is that
> the too pools are needed because task scheduling in Cardelli's scheme is
> non-preemptive, independent of readiness to perform a communication on a
> channel. That is, actual rendezvous may occur after both reading and writing
> tasks are ready to communicate.

I understand. I did my own design without preemptive
scheduling as well, but built the needed scheduling
into the send/receive calls. It is outlined below.

>>Interesting is that they don't even take processes as
>>first-class objects. After introducin channels, I also
>>found my tasklets less useful than before, and maybe
>>they will survive only in a shadowy existance.
> 
> This was designed in the context of languages and formalisms like CSP and
> Squeak (Cardelli and Pike's Squeak), in which tasks are not first-class
> objects. In the introduction he says "processes are not denotable values".

I assume this is a necessary restriction, in order to
prevend direct manipulations and to preserve CSP
properties?

>>Anyway, what I didn't grasp really yet is how to
>>implement PAR as a multiple select on a group
>>of channels.
> 
> I'm not sure of why you would need this, but maybe I've just been away from
> this stuff too long. PAR just puts a bunch of tasks in the runnable pool.

This is where I stumbled. For me, it was only one
task, waiting for multiple channels. But well, this
was just a special case of PAR which I saw in LIMBO.
Limbo has a special case where you wait on an array
of channels, all for input.
The more general case has different code for every
branch, and these code pieces appear to be again
tiny tasks, right?

> When any of them wants to communicate, it suspends in the appropriate
> channel queue waiting for a matching communication request (the matching
> request may already be available, in which case the scheduler is free to do
> the rendezvous and move the satisfied tasks to the runnable pool). In other
> words, I don't understand why PAR would need to create a collection from the
> channels used by the PARed tasks.

Since I thought of the special case of one task
waiting for multiple channels, all in the same
manner. In the more general case, with a large
ALT construct, syntactically like a case, I
expect this is done with as many small tasks,
together with guards, and then I can imagine
to arrange these tasks in groups per channel.
You've shed quite some light on it, thanks!

...

>>thanks so much for your support, I really need to
>>learn more, soon!
> 
> Welcome, and I hope Stackless prospers as it deserves.

I'l do my very best to really make deserve it.

> PS. For a different but intriguing approach to communication in an OO
> framework, check out Cardelli's recent paper on concurrency abstractions for
> C#.
> 
> http://research.microsoft.com/Users/luca/Papers/Polyphony%20ECOOP.A4.pdf

Whow! I will check that one ASAP.

Here the internal comments of my channel stuff.
I had to write these explicitly, in order to
be able to implement them. Afterwards, it worked
on the first shot.

/**********************************************************

   The central functions of the channel concept.
   A tasklet can either send or receive on a channel.
   A channel has a queue of waiting tasklets.
   They are either all waiting to send or all
   waiting to receive.
   Initially, a channel is in a neutral state.
   The queue is empty, there is no way to
   send or receive without becoming blocked.

   Sending 1):
	A tasklet wants to send and there is
	a queued receiving tasklet. The sender puts
	its data into the receiver, unblocks it,
	and inserts it at the top of the runnables.
	The receiver is scheduled.
   Sending 2):
	A tasklet wants to send and there is
	no queued receiving tasklet.
	The sender will become blocked and inserted
	into the queue. The next receiver will
	handle the rest through "Receiving 1)".
   Receiving 1):
	A tasklet wants to receive and there is
	a queued sending tasklet. The receiver takes
	its data from the sender, unblocks it,
	and inserts it at the end of the runnables.
	The receiver continues with no switch.
   Receiving 2):
	A tasklet wants to receive and there is
	no queued sending tasklet.
	The receiver will become blocked and inserted
	into the queue. The next sender will
	handle the rest through "Sending 1)".
  */

Note that the above works simply by means of channel
functions, which take over the necessary actions
of putting tasklets into runnable state or blocking
them etc. All my tasklet-related machinery works
with a "schedule-on-demand" concept, that means,
scheduling is explicitly performed when there is
no running tasklet. The rest will be done through
a peemptive scheduler, which makes the system schedule
when there are no rendevouz actions, but the rendevouz
stuff works alone.

cheers & thanks again - chris

-- 
Christian Tismer             :^)   <mailto:tismer at tismer.com>
Mission Impossible 5oftware  :     Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9a     :    *Starship* http://starship.python.net/
14109 Berlin                 :     PGP key -> http://wwwkeys.pgp.net/
work +49 30 89 09 53 34  home +49 30 802 86 56  pager +49 173 24 18 776
PGP 0x57F3BF04       9064 F4E1 D754 C2FF 1619  305B C09C 5A3B 57F3 BF04
      whom do you want to sponsor today?   http://www.stackless.com/







More information about the Python-list mailing list