[Stackless] Just Not Getting One Aspect of Tasklets and Channel Receive on Pong Example

Christian Tismer tismer at stackless.com
Sat Mar 13 17:34:32 CET 2010


On 3/12/10 9:44 PM, Carl, Andrew F (AS) wrote:
>
> The pong example on p. 13 of the "Why Stackless" manual is unclear to 
> me.  It appears that the tasklet statement puts the task on the queue 
> once, but yet it seems that the send to the "while receive" is 
> effectively creating another tasklet on the queue. It would seem that 
> they should bounce back and forth only once each without the addition 
> of a new tasklet statement. Could someone please clarify this?
>
An unambiguous link would be preferrable to readers, like this:

http://members.verizon.net/olsongt/stackless/why_stackless.html#pingpong-stackless-py-stackless-ping-pong-example

#
# pingpong_stackless.py
#

import stackless

ping_channel = stackless.channel()
pong_channel = stackless.channel()

def ping():
     while ping_channel.receive(): #blocks here
         print "PING"
         pong_channel.send("from ping")

def pong():
     while pong_channel.receive():
         print "PONG"
         ping_channel.send("from pong")



stackless.tasklet(ping)()
stackless.tasklet(pong)()

# we need to 'prime' the game by sending a start message
# if not, both tasklets will block
stackless.tasklet(ping_channel.send)('startup')

stackless.run()


Assuming that this is the code you are referring to, I am trying
to understand your question.

/Two tasklets are created which are initially blocking on their channel./

stackless.tasklet(ping)()
stackless.tasklet(pong)()

/Going into details:/

stackless.tasklet(ping)

/is the constructor call of a tasklet, bound to function ping.
A more explicit notation would be/

task = stackless.tasklet()  # not bound to a function
task.bind(ping)             # bound to ping
task.setup()                # set empty argument list

/After the setup, the ping tasklet is ready to run. It is sitting in
the runnables queue, right after the implicit main tasklet.
/

/The same thing as above repeats for the pong tasklet.
/

stackless.tasklet(pong)()

/We have a circular list of runnable tasklets:
/

main<-    still executing
ping    |  |   paused
pong     ->     paused

/Now we enter the last line before the run():/

# we need to 'prime' the game by sending a start message
# if not, both tasklets will block
stackless.tasklet(ping_channel.send)('startup')

/This tasklet does the equivalent of/

     ping_channel.send('startup')

/but it is written in this deferred form, so that all tasklet activities 
are done
in the run() context. This is not needed for the example to work, but seems
to be the author's intent, for more clarity.

We have now the following circular queue picture:/

main<-    still executing
ping    |  |   paused
pong    |  |   paused
<???>     ->     paused

/Now we enter the final statement, which does it all:/

stackless.run()

/Main gets removed from the runnables queue, to let the other tasklets
do their thing. ping is the next available tasklet and it runs:
/

ping<-    current
pong    |  |   paused
<???>     ->     paused

/ping starts to run, but immediately blocks on the empty ping_channel:
/
def ping():
     while ping_channel.receive(): #blocks here
         print "PING"
         pong_channel.send("from ping")

/ping gets removed from the runnables queue and stored in the
ping_channel. So the next available tasklet is pong./

pong<-    current
<???>     ->     paused

def pong():
     while pong_channel.receive():
         print "PONG"
         ping_channel.send("from pong")


/The same happens to pong, since pong_channel is empty.
It gets blocked into pong_channel. Our only available
tasklet is now the nameless <???>./

<???>     <->    current. sends 'startup' on ping_channel
                and exits.

/Now we are back in ping, right after the receive call. ping is
our only active tasklet:/

ping<->    current. prints 'PING', then sends
                'from ping' on pong_channel.

def ping():
     while ping_channel.receive(): #blocks here
         print "PING"
         pong_channel.send("from ping")

PING


/ping gets blocked after sending on pong_channel, and pong
is now our only active tasklet:/

pong<->    current. prints 'PONG', then sends
                'from pong' on ping_channel.

PONG

/Now that game continues until you hit CTL-C. The main tasklet will th//en
wake up and report the exception./

hope this helps -- chris


p.s.:
If people have questions like this, I'd like to refer them to
http://www.disinterest.org/resource/stackless/2.6.4-docs-html/stackless-python.html
This is the one and only reference documentation that covers it all!

-- 

Christian Tismer             :^)<mailto:tismer at stackless.com>
tismerysoft GmbH             :     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 802 86 56  mobile +49 173 24 18 776  fax +49 30 80 90 57 05
PGP 0x57F3BF04       9064 F4E1 D754 C2FF 1619  305B C09C 5A3B 57F3 BF04
       whom do you want to sponsor today?http://www.stackless.com/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.stackless.com/pipermail/stackless/attachments/20100313/099dbe45/attachment.htm>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: Attached Message Part
URL: <http://www.stackless.com/pipermail/stackless/attachments/20100313/099dbe45/attachment.asc>


More information about the Stackless mailing list