Hi Folks:
I have started to prototype a Stackless select() function. For now
I want something similar to Go. I have success with the function using
stackless.py over CPython. Carl Boltz and Stephan Diehl have been
really helpful. I am still running tests and playing with
algorithms but the initial code is pretty straightforward. I am also
writing documentation that I will post later with a new version of
stackless.py. I am not sure how new features are handled in the PyPy
or for that matter Stackless world.
the signature is:
(channel, value) = stackless.select([cases])
case, a tuple of (channel, operation, value) where operation is
{RECEIVE, SEND}
RECEIVE = -1, SEND = 1
I have attached an initial version.
An early observation....
I am thinking to simplify implementing the code for C based Stackless
(as a subclass as per Richard Tew's suggestions), maybe two function
could be added to channel.
channel._queueTasklet(current tasklet, operation)
channel._removeTasklet(tasklet, operation)
Any feedback?
Cheers,
Andrew
# Select.py
# Andrew Francis
# December 18th, 2009
#
# This is an initial version of the Select function for Stackless.py
# The object of this version is to get Select to work and learn
# I am new to stackless.py
def select(list):
result = None
ready = []
source = getcurrent()
# is there a channel that will not block? If so, put it on the
# ready list
for channel, operation, value in list:
if (channel.balance > 0 and operation == RECEIVE) or \
(channel.balance < 0 and operation == SEND): \
ready.append((channel,operation, value))
"""
if there are ready channels, randomly select one
and return from select(). In the Pike paper this is done to
guard against 'chatty' processes. Is this really necessary
in the Stackless world given the difference in schedulers?
"""
l = len(ready)
if l != 0:
unblockedChannel, operation, value = ready[random.randint(0, l - 1)]
result = unblockedChannel._channel_action(value, operation)
else:
# for some reason, channel action does this instead of using a boolean?
source.blocked = operation
for channel, operation, value in list:
channel.queue.append(source)
channel.balance += operation
source.selectedChannels[channel] = (operation, value)
_scheduler_remove(source)
schedule()
#lets be safe for now
result = source.tempval
unblockedChannel = source.selected
source.selected = None
source.blocked = False
del(source.selectedChannels[unblockedChannel])
# now remove self from all the other channels, ouch
for channel, (operation, value) in source.selectedChannels.items():
channel.balance -= operation
channel.queue.remove(source)
return unblockedChannel, resultimport stackless
import sys
"""
test5.py
the purpose of this test is to check whether select will properly
block, unblock and return the correct value
"""
RECEIVE = -1
SEND = 1
def sender(ch):
stackless.schedule() #ensure that selector goes first
ch.send("hello world")
print "Sender done"
def selector(list):
try:
channel, result = stackless.select(list)
print "THE RESULT FROM SELECT ->", channel, result
except:
print sys.exc_info()
if __name__ == "__main__":
list = []
list.append((stackless.channel(),RECEIVE, None))
list.append((stackless.channel(),RECEIVE, None))
list.append((stackless.channel(),RECEIVE, None))
list.append((stackless.channel(),RECEIVE, None))
list.append((stackless.channel(),RECEIVE, None))
stackless.tasklet(selector)(list)
stackless.tasklet(sender)(list[0][0])
stackless.run()
print "THE PROGRAMMING IS ENDING"
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless