[Stackless] walking off the end of a channel

Richard Tew richard.m.tew at gmail.com
Thu Apr 19 09:31:28 CEST 2007


On 4/19/07, Matt Provost <mprovost at termcap.net> wrote:
> I found out that if you receive() on a channel until it's finished, then
> it appears that the receiving tasklet dies. I'm not sure if it detects a
> deadlock and kills it, or what I should do about it.
...
> If you run the sequence_send and sequence_receive tasklets, it will
> print 0 through 9, but not "done!".

sequence_receive iterates over a channel.  A channel is designed to
give you what is waiting or block waiting for it to be sent.  If you
iterate over a channel, you are saying keep sending me things and I
will wait indefinitely should you run out.

How can it know you have finished sending?

The receiving tasklet has not died, it is still on the channel waiting.

> iter_receive works, but only if it
> loops less than or equal to the number of messages sent across the
> channel. If you change xrange(10) to xrange(11), it won't print "done!"
> anymore.

Right.  If you ask it to receive and there is nothing coming, it will
block on the channel until it gets it.

> The program itself doesn't die, you can put something after
> stackless.run() and it will work.

This is something a lot of people miss.  When a tasklet is blocked on
a channel it is not running, if there are no actual running tasklets..
then stackless.run() will exit and the tasklet will be left on the
channel.

> I just noticed this because usually my tasklets just loop over a
> channel, but I wrote one that does some cleanup afterwards and that code
> isn't being executed. It seems like this should work, but maybe I'm
> missing something? What other way is there to accomplish this?

Just that if there isn't something waiting on the other side of a
channel, whether you are going to send or receive, the current tasklet
will block on the channel waiting for it.  So make sure you do the
same number of sends as receives, if you are going to have your code
exit when done.  Or send some final token down the channel to signal
that the receiver should exit.  Or whatever, there are more
possibilies if you understand what is going on.

>>> def sender(chan):
...     for i in xrange(10):
...             chan.send(i)
...     print "sender done"
...
>>> def receiver(chan):
...     for v in chan:
...             print "received" v
  File "<stdin>", line 3
    print "received" v
                     ^
SyntaxError: invalid syntax
>>> def receiver(chan):
...     for v in chan:
...             print "received", v
...     print "receiver done"
...
>>> chan = stackless.channel()
>>> stackless.tasklet(sender)(chan)
<stackless.tasklet object at 0x00C11270>
>>> stackless.tasklet(receiver)(chan)
<stackless.tasklet object at 0x00C112B0>
>>> stackless.run()
received 0
received 1
received 2
received 3
received 4
received 5
received 6
received 7
received 8
received 9
sender done
>>> chan.send_exception(StopIteration)
receiver done
>>>

Hope this helps,
Richard.

_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless



More information about the Stackless mailing list