I poked around in Eventlet this morning – between shopping runs and helping Karen move things around in the basement. I’d hoped to knock out a quick hackysack experiment with that stuff – since it sounded about the same – and see how it did. I over-estimated by ability to quickly grok Eventlet, and it’s underpinnings of greenlet as well.
Bob Ippolito hacked this stuff together after the same conversations that revolved around how stackless does its magic. That dude is always doing something wild and forward.
What I’ve finally concluded is that the Eventlet stuff is a nice socket-based processing engine (read web server thingy) using the greenlets – but way more than I’d need for the basics to pull together the hackysack example. Seems like heading straight down to the greenlets themselves is what I’d want to do to make it – only I’m not fully understanding all the pieces and parts to make the hackysack example. I was thinking that Eventlet would have the higher level API’s that made it similiar to a Stackless Tasklet or a Kamaelia Component. Alas, it doesn’t appear so… or I’m just too dense to clue it in anyway.
Anyway, I’ve poked around this morning, realized I’m a bit lost – and so I’m going to give it a break to see if my rear-brain can catch up with some of the core concepts here.
Oh – here’s the code that doesn’t work as yet:
import greenlet import Queue import sys import random class hackeysacker: counter = 0 def __init__(self,name,circle): self.name = name self.circle = circle circle.append(self) self.messageQueue = Queue.Queue() self.g = greenlet(self.goLoop()) def incrementCounter(self): hackeysacker.counter+=1 def goLoop(self): while 1: msg = self.messageQueue.get() if msg == 'exit': return print "%s got hackeysack from %s" % (self.name,msg.name) kickTo = self.circle[random.randint(0,len(self.circle)-1)] while kickTo is self: kickTo = self.circle[random.randint(0,len(self.circle)-1)] print "%s kicking hackeysack to %s" % (self.name, kickTo.name) kickTo.switch(self) hackeysackers = 5 turns = 1 def runit(hs=5,ts=5): global hacksackers,turns hackeysackers = hs turns = ts hackeysacker.counter = 0 circle=[] one = hackeysacker('1',circle) for i in range(hackeysackers): hackeysacker(`i`,circle) one.g.switch(one) if __name__ == '__main__': runit()
why it does not work is because Queue and greenlets aren’t designed to work together.
All your greenlets, in fact, run in the same thread, so when messageQueue.get() blocks
because the queue is empty it blocks every other greenlet you have, giving your program
no chance to put something in the queue.
in eventlet, there’s coros.queue that works as expected. however, with eventlet, you don’t create greenlets
directly and switch() between them, instead you spawn() them (which is quite easy) and use
communication primitives provided by eventlet, classes like coros.queue, coros.event.
and btw, use this eventlet
http://devel.ag-projects.com/~denis/cgi-bin/hgweb.cgi
it’s the most stable eventlet available at this point.
LikeLike