channel.close() less useful than thought #53

Description
Originally reported by: Kristján Valur Jónsson (Bitbucket: krisvale, GitHub: kristjanvalur)
Writing a unittest for sending a sequence through a channel, I tried the obvious, but failed:
#!python
def testSequence(self):
def sender():
self.c.send_sequence(xrange(10))
self.c.close()
data = []
def receiver():
for i in self.c:
data.append(i)
stackless.tasklet(sender)()
stackless.tasklet(receiver)()
stackless.run()
self.assertEqual(data, range(10))
self.assertTrue(self.c.closed)
This doesn't work, however. The receiver is stuck on a iter.next call at the end.
This is because when the sender calls close, the channel balance is already -1. So it is set into 'closing' state, but that is it.
In order to do this properly, the functions needed to be tweaked like this:
#!python
def sender():
self.c.send_sequence(xrange(10))
self.c.close()
# this needs to change, close does not wake up a receiver, we must pump it
while self.c.closing and not self.c.closed:
self.c.send(None)
def receiver():
for i in self.c:
data.append(i)
#remove the extra "pump" nones at the end....
while data[-1] is None:
data.pop(-1)
data.append(10)
I wonder if this system is how we want to do it? Wouldn't it be nicer if close() were immediate? It would wake up any blocked tasklets right away? We would get rid of the 'closing' attribute, or make it synonomous with 'closed'.
As it is, I don't really se a use case for the sequence protocol if it needs to be shored up in boilerplate anyway.
Is there a use case for the current closing/closed state transfer?